Scripting Language
An AutoHotkey script is basically a set of instructions for the
program to follow, written in a custom language exclusive to AutoHotkey.
This language bears some similarities to several
other scripting languages, but also has its own unique strengths and pitfalls.
This
document describes the language and also tries to point out common
pitfalls.
See Concepts and Conventions for more general explanation of various concepts utilised by
AutoHotkey.
There are two distinct styles of syntax used in AutoHotkey: legacy
syntax and expressions.
Table of Contents
General Conventions
Comments
Expressions
Strings / Text
Variables
Operators
Function Calls
Operators for Objects
Expression Statements
Legacy Syntax
Commands
OutputVar and InputVar Parameters
Text Parameters
Numeric Parameters
% Expression
Documentation Conventions
Optional Parameters
Expressions vs Legacy
Syntax
Different Equals
Commands vs Functions
Control Flow Statements
Control Flow vs Commands
If Statement
Loop Statement
Not Control Flow
Structure of a Script
Auto-execute Section
Subroutines
User-Defined Functions
#Include
Miscellaneous
Dynamic Variables
Pseudo-arrays
Associative pseudo-arrays
Commands which create pseudo-arrays
Labels
General Conventions
Names: Variable and function names are not case sensitive (for
example, CurrentDate is the same as currentdate). For details such as maximum
length and usable characters, see Names.
No typed variables: Variables have no explicitly defined type;
instead, a value of any type can be stored in any variable (excluding
built-in variables). Numbers may be automatically converted to
strings (text) and vice versa, depending on the situation.
Declarations are optional:
Except where noted on the functions page,
variables do not need to be declared; they come into existence
simply by using them (and each variable starts off empty/blank).
Spaces are mostly ignored:
Indentation (leading space) is important for writing readable code, but is not
required by the program and is generally
ignored. Spaces and tabs are generally
ignored at the end of a line, within an expression (except between quotes), and
before
and after command parameters. However, spaces are significant in
some cases, including:
Function and method calls require
there to be no space between the function/method name and (.
Spaces are required when performing concatenation.
Spaces may be required between two operators, to remove ambiguity.
Single-line comments require a leading space if they are not at the start of the line.
Line breaks are meaningful:
Line breaks generally act as a statement separator, terminating the previous
command or expression. (A
statement is simply the
smallest standalone element of the language that expresses some action to be
carried out.) The exception to this is line
continuation (see below).
Line continuation: Long lines can be divided up into a collection
of smaller ones to improve readability and maintainability. This is
achieved by preprocessing, so is not part of the language as such.
There are two methods:
Line continuation, where lines that begin with an
expression operator (except ++ and --) are merged with the previous line. Lines
are merged regardless of whether the line actually contains an
expression.
Continuation sections, where multiple lines are merged with the line above the section.
The start and end of a continuation section
are marked with ( and ) (both symbols must appear at the beginning of a line, excluding
whitespace).
Comments
Comments are portions of text within the script which are ignored
by the program. They are typically used to add explanation or disable
parts of the code.
Scripts can be commented by
using a semicolon at the beginning of a line. For example:
; This entire line is a comment.
Comments may also be added at the end of a line, in which case the
semicolon must have at least one space or tab to its left. For
example:
Run Notepad ;
This is a comment on the same line as a command.
In addition, the /* and */ symbols can be used to
comment out an entire section, but
only if the symbols appear at the beginning of a line as in this example:
/*
MsgBox, This line is commented out
(disabled).
MsgBox, Common mistake: */ this does not end the comment.
MsgBox, This line is commented out.
*/
Since comments are ignored when a script is launched, they do not
impact performance or memory utilization.
The default comment character (semicolon) can be changed to some
other character or string via #CommentFlag.
Expressions
Expressions are combinations of one or more values, variables, operators and function calls. For example, 10, 1+1 and MyVar are valid
expressions. Usually, an expression takes one or more values as
input, performs one or more operations, and produces a value as the
result. The process of finding out the value of an expression is
called evaluation. For example, the expression
1+1 evaluates to the
number 2.
Commands are designed to take a
list of parameters and perform only a single action per line, whereas simple expressions
can be pieced together to form increasingly
more complex expressions. For example, if Discount/100 converts a discount percentage to a fraction, 1 - Discount/100 calculates a fraction representing the remaining amount, and Price
* (1 - Discount/100) applies it to produce the net
price.
Values are numbers, objects or strings. A
literal value is one written physically in the script; one that you can see
when you look at the
code.
Strings / Text
For a more general
explanation of strings, see Strings.
A string, or string of characters, is just a text value. In an expression,
literal text must be enclosed in quotation marks to differentiate it
from a variable name or some other expression. This is often
referred to as a quoted literal string, or just quoted string. For example,
"This is a quoted string.".
To include an actual quote character inside a quoted string,
specify two consecutive quotes as shown twice in this example: "She
said,
""An apple a day.""".
Quoted strings can contain escape sequences such as `t (tab), `n (linefeed), and `r (carriage return). Unlike unquoted
text, it is not
necessary to escape commas or percent signs, as quoted strings
cannot contain variables. The use of the `" escape sequence to produce a literal quote-character is currently not supported;
instead, use two consecutive quotes as shown above.
Variables
For a basic explanation and
general details about variables, see Variables.
Variables can be used in an expression simply by writing the
variable's name. For example, A_ScreenWidth/2. However, variables
cannot be used inside a quoted string. Instead, variables and
other values can be combined with text through a process called
concatenation. There
are two ways to concatenate values in
an expression:
Implicit concatenation: "The value is " MyVar
Explicit concatenation: "The value is " . MyVar
Implicit concatenation is also known as auto-concat. In both
cases, the spaces preceding the variable and dot are mandatory.
The Format function
can also be used for this purpose. For example:
MsgBox % Format("You are
using AutoHotkey v{1} {2}-bit.", A_AhkVersion, A_PtrSize*8)
To assign a value to a
variable, use the := assignment operator, as in MyVar
:= "Some text".
Percent signs within an expression are used to create dynamic
variable references and dynamic function calls. Most of the time these
constructs are not needed, so in general, variable names should
not be enclosed in percent signs within an expression.
Operators
Operators take the form of a symbol or group of symbols such as + or :=, or one
of the words and, or, not or new. They take one, two or
three values as input and return a value as the
result. A value or sub-expression used as input for an operator is called an operand.
Unary operators are written either before or after a single
operand, depending on the operator. For example, -x or not keyIsDown.
Binary operators are written in between their two operands. For
example, 1+1 or 2 * 5.
AutoHotkey has only one ternary
operator, which takes the form condition ? valueIfTrue : valueIfFalse.
Some unary and binary operators share the same symbols, in which
case the meaning of the operator depends on whether it is written
before, after or in between two values. For example, x-y performs
subtraction while -x inverts the sign of x (producing a positive value from a negative value and vice versa).
Operators of equal precedence such as multiply (*) and
divide (/) are evaluated in left-to-right order unless otherwise specified
in the
operator table. By contrast, an operator of lower precedence such as add (+) is
evaluated after a higher one such as multiply (*). For
example, 3 + 2 * 2 is evaluated as 3 + (2 * 2). Parentheses may be used to override precedence as in this
example: (3 + 2) * 2
Function Calls
For a general explanation
of functions and related terminology, see Functions/Commands.
Functions take a varying number of inputs, perform some action or
calculation, and then return a
result. The inputs of a function are
called parameters or arguments. A function is called simply
by writing its name followed by its parameters enclosed in parentheses. For
example, GetKeyState("Shift") returns (evaluates to) 1 if the Shift key is being held down or 0 otherwise.
Note: There must not be any space between the function name and open
parenthesis.
When compared to commands, the requirement for parentheses may seem cryptic or verbose at
first, but they are what allows a function call to be combined with other operations. For example, the
expression GetKeyState("Shift", "P") and
GetKeyState("Ctrl", "P") returns 1 only if both keys are being physically held down.
Function names are always global, and are separate to variable
names. For example, Round can be both a variable name and a function
name, and Round := 1 will not
affect Round(n) in any way.
Operators for Objects
There are other symbols used in expressions which don't quite fit
into any of the categories defined above, or that affect the meaning of
other parts of the expression, as described below. These all
relate to objects in some way.
Providing a full explanation of what each
construct does would require introducing more concepts which are
outside the scope of this section.
Alpha.Beta is often called member
access. Alpha is an ordinary variable, and could be replaced with a function
call or some other sub- expression
which returns an object. When evaluated, the object is sent a request
"give me the value of property Beta",
"store this value in property Beta" or "call the method named Beta". In other words, Beta is a name which has meaning to the
object; it is not a local or
global variable.
Alpha.Beta() is a method call, as described above.
Alpha.Beta[Param] is a specialised form of
member access which includes additional parameters in the request. While Beta
is a simple name, Param is an ordinary
variable or sub-expression, or a list of sub-expressions separated by commas
(the same as in a function's
parameter list).
Alpha[Index] has a similar function to Alpha.Beta, but
each part is interpreted in a more standard way. That is, both Alpha and Index
are variables in this case, and could be replaced with virtually
any sub-expression. This syntax is usually used to retrieve an element of
an array or associative array.
new ClassName() is used to instantiate a
class, or create an object derived from another object. Although this looks
like a function call, ClassName is actually an ordinary
variable. Similarly, new Alpha.Beta() would
create an object derived from the object returned by
Alpha.Beta; Beta is neither a
function nor a method. If the optional parentheses are present, they may
contain parameters for the object's __New
method.
[A, B, C] creates
an array with the
initial contents A, B and C (all variables in this case), where A is element 1.
{Key1: Value1, Key2: Value2} creates an associative array from a
list of key-value pairs. A value can later be retrieved by its
associated key. Writing a plain word (consisting of alphanumeric
characters, underscore and non-ASCII characters) to the left of : is
equivalent to enclosing that word in quotation marks. For example, {A: B} is
equivalent to {"A": B}. However, {(A):
B} uses the
contents of the variable A as the
key.
MyFunc(Params*) is a variadic function call. The asterisk must immediately precede the closing parenthesis at
the end of the function's
parameter list. Params
must be a variable or sub-expression which returns an array object. Although it
isn't valid to use Params* just
anywhere, it can be used in an array literal ([A, B,
C, ArrayToAppend*]) or indexer (Alpha[Params*]).
Expression Statements
Not all expressions can be used alone on a line. For example, a
line consisting of just 21*2 or "Some text" wouldn't
make any sense. An expression statement is an
expression used on its own, typically for its side-effects. Most expressions
with side-effects can be used this
way, so it is generally not necessary to memorise the details of
this section.
The following types of
expressions can be used as statements:
Assignments, as in x := y, compound assignments such as
x += y, and increment/decrement operators such as ++x and x--. However, in
AutoHotkey v1, ++, --, +=, -=, *= and /= have slightly different
behavior when used alone on a line, as they are actually equivalent to
EnvAdd, EnvSub, EnvMult or EnvDiv. For details, see
"Known limitations" under Assign in the table of operators.
Function calls such as MyFunc(Params). However, a standalone function call cannot be followed by an
open brace { (at the end of the
line or on the next line), because it would be confused with a
function declaration.
Method calls such as MyObj.MyMethod().
Member access using square
brackets, such as MyObj[Index], which can have side-effects like a function call.
Expressions starting with the new operator, as in new ClassName, because sometimes a class
can be instantiated just for its side-effects.
Ternary expressions such as x ? CallIfTrue()
: CallIfFalse(). However, in AutoHotkey v1, command names take
precedence. For example, MsgBox
? 1 : 0 shows a
message box.
Expressions starting with (. However, there usually must be a matching ) on the same line, otherwise the line would be interpreted as the
start of a continuation section.
Expressions that start with any of those described above (but not
those described below) are also allowed, for simplicity. For example,
MyFunc()+1 is currently allowed,
although the +1 has no effect and its result is discarded. Such
expressions might become invalid in the future due to enhanced error-checking.
Member access using a dot (once or in a series), such as ExcelApp.Quit or x.y.z. However, unless
parentheses are used (as in a method call), this
cannot be the prefix of a larger expression. For example, ExcelApp.Quit, xxx is prohibited due to the
apparent similarity to
command syntax.
Legacy Syntax
Legacy or command
syntax generally only allows a single action per line, but uses fewer
characters to perform simple tasks such as
sending keystrokes or running a program. The
syntax consists of command and variable names, unquoted text and a few symbols
such as ,, = and %.
Unquoted text is simply text, not enclosed in quote marks, just
straight up. Since the text has no explicit start and end marks, it ends at
the end of the line or the end of the parameter. Leading and
trailing spaces and tabs are ignored. Within unquoted text, the following
characters have special meaning:
%: Enclose a variable name in percent signs to include the contents
of that variable. For example, The
year is %A_Year%.
Note: Variable names are
not always enclosed in percent signs;
they are required only within unquoted text. Percent signs should
not be used anywhere else, except to create a dynamic
variable reference or dynamic function call.
Note: Only a plain
variable name can be used. Array elements, properties and other expressions are not supported.
,: Comma is used to delimit (separate) the
parameters of a command, with some exceptions. It has no special meaning
when used
in an assignment or comparison, so is interpreted literally in
such cases.
`: An escape character is
usually used to indicate that the character immediately following it should be
interpreted differently than
it normally would. For example, `% produces a literal percent sign and `, produces a literal comma. Some other common escape
sequences produce special characters, such as `t (tab), `n (linefeed), and `r
(carriage return).
Commands accept a mixture of unquoted text, variable names and numeric expressions.
Send, The time is %A_Hour%
o'clock.
Legacy assignment assigns unquoted text to a variable.
Clipboard = This text is copied to
the clipboard.
If statements perform an action only if the specified condition is met.
If Var = Text value
There are also several other control
flow statements (such as loops) which use legacy syntax similar to commands.
Commands
A command is an instruction to carry out a specific predefined
action. "Command" may also refer to a specific predefined action,
such as MsgBox.
The set of available commands is predefined and cannot be changed by the script.
A command is called simply
by writing its name at the beginning of a line, optionally followed by
parameters. For example:
MsgBox, The time is %A_Hour%
o'clock.
The comma separating the
command name from its parameters is optional, except in the following cases:
When it's
necessary to prevent the line from being interpreted as a legacy assignment or assignment expression.
MsgBox, := This would be an assignment without the comma.
When the first parameter is blank.
MsgBox,, Second,
Third
When the
command is alone at the top of a continuation section.
Each parameter of a command
may accept different syntax, depending on the command. There are four types of
parameters:
OutputVar
InputVar
Text
Number
In most cases the percent prefix can be
used to pass an expression.
OutputVar and InputVar Parameters
OutputVar and InputVar parameters require a
variable name or dynamic variable reference. For example:
; Replace all spaces with pluses:
StringReplace, NewStr, OldStr,
%A_Space%, +, All
This command reads the
value from OldStr (the InputVar) and stores the result in NewStr (the
OutputVar).
Note: Only a plain
variable can be used as an OutputVar. Array elements, properties and
other expressions are not
supported.
InputVar parameters can accept an expression only when the percent
prefix is used.
However, the prefix is not supported in the Var
parameters of legacy If commands, so If (expression) should
be used instead.
Text Parameters
Text parameters accept unquoted
text. For example:
MsgBox, The time is %A_Hour% o'clock.
Since commas and percent
signs have special meaning, use the escape sequence `, to specify a literal comma and
`% to specify a literal
percent sign. For clarity, it is best to always escape any comma
which is intended to be literal, but escaping comma is optional in the
following cases:
In the
last parameter of any command.
In the Text parameter of MsgBox, which has smart comma handling.
To include a leading or
trailing space or tab, use the built-in variables %A_Space% and %A_Tab% or a
forced expression such as %
" x ". [v1.1.06+]: Whitespace
can also be preserved by preceding the space or tab with an escape character, except
for whitespace at the end of a line.
Text parameters can also accept a
forced expression.
Numeric Parameters
Numeric parameters accept a literal number or an expression, and can
be identified by phrasing like "This parameter can be an
expression."
For historical reasons,
simple variable references alone or combined with digits are not interpreted as
expressions. For example:
Sleep %n%000 ; Sleep for n
seconds.
Sleep %m% ; Sleep for m
milliseconds.
To perform a double-deref in such cases, enclose the
expression in parentheses: Sleep
(%m%)
Note that mixed-type parameters such as SetTimer's second
parameter, which sometimes accepts a number and sometimes accepts a
string such as On or Off, are actually Text parameters, and as such,
they do not accept expressions unless the percent
prefix is used.
Numeric parameters allow and ignore the percent prefix.
% Expression
Although purely numeric parameters accept an expression by
default, all other parameters of commands do not. Specify a percent sign
followed by a space or tab to force a parameter to accept an expression. For example, all of the following are effectively identical
because Sleep's first
parameter is expression-capable:
Sleep MillisecondsToWait
Sleep %MillisecondsToWait%
Sleep % MillisecondsToWait
Note: Using the
percent-space prefix in a numeric parameter does not necessarily force it to be an expression.
All parameters support the percent-space prefix except for:
The Var parameter of any legacy If command. Users can avoid
confusion by always using if (expression).
OutputVar parameters,
which accept a variable reference using the same syntax as expressions.
Some users may find it easier to always force an expression,
keeping to one consistent syntax (expression syntax) as much as possible.
Documentation Conventions
At the top of each page
which documents a command, there is usually a block showing syntax, like this:
Run, Target , WorkingDir,
Max|Min|Hide|UseErrorLevel, OutputVarPID
The square brackets denote
optional parameters; the brackets themselves must be omitted from the actual
code.
Sometimes the value or values a parameter accepts are written
directly in the syntax block. For example, the third parameter of Run
shown above accepts one or more of the words shown, as text. The
pipe symbol denotes alternatives; the symbol itself should be omitted
from the actual code. The exact syntax of the
parameter is described in the Parameters table, and varies between commands.
Optional Parameters
Optional parameters can simply be left blank. The comma preceding
an optional parameter can also be omitted if all subsequent
parameters are omitted. For example, the Run command
can accept between one and four parameters. All of the following are valid:
Run, notepad.exe, C:\
Run, notepad.exe,, Min
Run notepad.exe, , , notepadPID
Expressions vs Legacy
Syntax
Many command parameters do
not accept expressions by default. Use the percent-space
prefix at the beginning of a parameter to
evaluate that parameter as an expression. In the following
examples, the expression is shown on the first line (beginning after the percent sign), with pure legacy syntax shown on the second line.
MsgBox % 1+1 ; Shows
"2"
MsgBox 1+1 ; Shows "1+1"
Literal text in an
expression is always enclosed in quote marks. These are called quoted strings.
MsgBox % "This is text."
MsgBox This is text.
Variables in an expression
are never enclosed in percent signs, except to create a double reference.
MsgBox % A_AhkVersion
MsgBox %A_AhkVersion%
Variables cannot be used
inside a quoted string.
MsgBox % "Hello %A_UserName%." ; Shows "%A_UserName%"
MsgBox Hello
%A_UserName%. ; Shows your username.
Instead, values are concatenated by writing them in sequence, separated by a space or tab, or a
dot surrounded by spaces.
MsgBox % "Hello " .
A_UserName . "." ; Shows your username.
One alternative is to use
the Format
function, which can also format the parameter value in various ways.
MsgBox % Format("Hello {1}.", A_UserName) ;
{} also works in place of {1}.
A value is assigned to a variable with := instead of =:
MyVar := "This is text."
MyVar = This is text.
Comparisons are performed
using the same symbols as legacy If: =, <> or !=, >, >=, < and <=.
if (Var1 = Var2)
if Var1 = %Var2%
In an expression, both values can be simple values or complex
sub-expressions. A comparison can also be combined with other
conditions using operators such as and and or (which
are equivalent to && and ||).
if (Var1 >= Low and Var1 <= High)
if Var1 between %Low% and %High%
Different Equals
One common mistake is to
write = where := is
needed. For example:
Total = A + B ; Assigns the literal text "A + B"
This can be difficult to avoid (at least until such time as the
legacy assignment syntax is removed), but it may help to always use :=
where an assignment is intended.
The equal sign (when not
used with another symbol, such as <=) has the following meanings:
Legacy assignment: Var = Value
Legacy If equal: if Var = Value
Case-insensitive equal: if
(Expr1 = Expr2) (also valid in other expressions, not just if)
Assign after comma: x:=1,
y=2, a=b=c (all are assignments due to a special rule)
Declare and initialize: local
x = Expr (always accepts an expression)
Set parameter default value: MyFunc(Param="Default value") {...
The first two cases can be avoided by always using the := assignment operator and if (expression).
For the last three cases, := should have been used instead of
=.
Commands vs Functions
In AutoHotkey v1, it is currently not possible to call a command
from an expression, or to call a function using the command syntax.
However, several commands have a function replacement.
Command Replacement
FileAppend FileOpen and File.Write
FileGetAttribFileExist
FileRead FileOpen and File.Read
GetKeyStateGetKeyState (the function returns 0 or 1, not "U" or "D")
IfExist FileExist
StringUpper Format("{:L}",
input),
Format("{:U}", input) or Format("{:T}", input)
StringLeft
Control Flow Statements
For a general explanation
of control flow, see Control Flow.
Statements are
grouped together into a block by
enclosing them in braces {}, as in C, JavaScript and similar languages, but usually the
braces must appear at the start of a line. Control flow statements
can be applied to an entire block or just a single statement.
The body of a
control flow statement is always a single group
of statements. A block counts as a single group of statements, as does a
control flow statement and its body. The following related
statements are also grouped with each other, along with their bodies: If with Else; Loop/For with Until; Try with Catch and/or Finally. In other words, when a
group of these statements is used as a whole, it does not always need to be enclosed in braces (however, some
coding styles always include the braces, for clarity).
Control flow statements which have a body and therefore must
always be followed by a related statement or group of statements: If,
Else, Loop, While, For, Try, Catch and Finally.
The following control flow
statements exist:
A block (denoted
by a pair of braces) groups zero or more statements to act as a single
statement.
An If statement causes
its body to be executed or not depending on a condition. It can be followed by
an Else
statement, which
executes only if the condition was not met.
Goto jumps to
the specified label and continues execution.
Gosub calls a subroutine.
Return returns
from a subroutine or function.
A Loop statement (Loop, While or For) executes its body repeatedly.
Break exits
(terminates) a loop.
Continue skips
the rest of the current loop iteration and begins a new one.
Until causes a
loop to terminate when an expression evaluates to true. The expression is
evaluated after each iteration.
Exception handling:
Try guards
its body against runtime errors and exceptions thrown by the throw command.
Catch executes its body after an exception is thrown within a try
statement (and only if an exception is thrown).
Finally executes its body when control is being transferred out of a try
or catch statement's body.
Throw throws
an exception to be handled by try/catch or display an error dialog.
Control Flow vs Commands
Control flow statements
have syntax resembling commands, and are often referred to as such, but some differ from
commands:
There are several types of If
statement, with each having different syntax.
For and several types of If statement use keywords or an
operator instead of commas to separate some of their parameters.
The opening brace of a block can be
written at the end of the same line as an If (expression), Else, Loop Count, While, For, Try,
Catch or Finally statement (basically any control flow statement which does not
use legacy
syntax). This is referred to as the One
True Brace (OTB) style. It is not supported by the other Loop
sub-commands or legacy If statement, as the brace would be
interpreted as a literal {
character.
Else, Try and Finally allow any valid statement to their right, as they require a body but have
no parameters.
If (expression) and While allow an
open parenthesis to be used immediately after the name. For example, if(expression).
For, While, Until and Throw always
accept expressions. They treat %var%, %var%000 and similar as
expressions, whereas numeric
parameters of other commands do not.
The requirement for backward-compatibility does not apply to these control flow
statements
as they are relatively new.
If Statement
If (expression)
evaluates an expression and executes the following statement only if the result
is true.
Common cause of confusion:
There are several other types of If statements, some of which look very similar
to If (expression). These
should be avoided in new scripts. If in doubt, it is
best to always begin the expression with an open-parenthesis. The
"legacy" If
statements are as follows:
If Var op Value, where
op is one of the following operators: =, <>, !=, >, >=, <, <=.
If Var [not] between Lower and Upper
If Var [not] in/contains MatchList
Any If statement which does not match one of the usages shown
above is interpreted as If (expression).
These are some common points of confusion related to legacy If statements:
Variable names must be enclosed in percent signs only on the right-hand side of the
operator.
between, in, contains and is are only valid in this context; they cannot be used in expressions.
Multiple conditions cannot be written on the same line (such as
with the and operator).
None of the parameters are expressions.
The following
"legacy" named If statements also exist:
IfEqual, IfNotEqual, IfLess, IfLessOrEqual, IfGreater and
IfGreaterOrEqual
If[Not]Exist
If[Not]InString
If[Not]WinActive
If[Not]WinExist
IfMsgBox
With the exception of
IfMsgBox, these are all obsolete and generally should be avoided in new
scripts.
Named If statements allow a command to be written on the same line, but mispelled command names are
treated as literal text. Such
errors may be difficult to detect.
Loop Statement
There are several types of
loop statements:
Loop Count executes
a statement repeatedly: either the specified number of times or until break is
encountered.
Loop Reg
retrieves the contents of the specified registry subkey, one item at a time.
Loop Files
retrieves the specified files or folders, one at a time.
Loop Parse
retrieves substrings (fields) from a string, one at a time.
Loop Read
retrieves the lines in a text file, one at a time.
While executes
a statement repeatedly until the specified expression evaluates to false. The
expression is evaluated before each
iteration.
For executes a statement once for each value or pair of values
returned by an enumerator, such as each key-value pair in an object.
Break exits
(terminates) a loop, effectively jumping to the next line after the loop's
body.
Continue skips
the rest of the current loop iteration and begins a new one.
Until causes a
loop to terminate when an expression evaluates to true. The expression is
evaluated after each iteration.
A label can be
used to "name" a loop for Continue and Break. This
allows the script to easily continue or break out of any number of
nested loops without using Goto.
The built-in variable A_Index
contains the number of the current loop iteration. It contains 1 the first time
the loop's body is executed. For the
second time, it contains 2; and so on. If an inner loop is enclosed by an outer
loop, the inner loop takes precedence. A_Index
works inside all types of loops, but contains 0 outside of a loop.
For some loop types, other built-in variables return information
about the current loop item (registry key/value, file, substring or line of
text). These variables have names beginning with
A_Loop, such as A_LoopFileName and A_LoopReadLine. Their values always
correspond to the most recently started (but not yet stopped) loop
of the appropriate type. For example, A_LoopField returns the current
substring in the innermost parsing loop, even if it
is used inside a file or registry loop.
t := "column 1`tcolumn
2`nvalue 1`tvalue 2"
Loop Parse, t, `n
{
rowtext := A_LoopField
rownum := A_Index ;
Save this for use in the second loop, below.
Loop Parse, rowtext, `t
{
MsgBox %rownum%:%A_Index% =
%A_LoopField%
}
}
Loop variables can also be used outside the body of a loop, such
as in a function or subroutine which is called from within a loop.
Not Control Flow
As directives, labels (including hotkeys and hotstrings), and
declarations without assignments are processed when the script is loaded
from file, they are not subject to control flow. In other words,
they take effect unconditionally, before the script ever executes any control
flow statements. Similarly, the #If directives such
as #IfWinActive cannot affect control flow; they merely set the criteria for any hotkey
labels and hotstrings specified in the code. A
hotkey's criteria is evaluated each time it is pressed, not when the #If
directive is
encountered in the code.
Structure of a Script
Auto-execute Section
After the script
has been loaded, it begins executing at the top line, continuing until a Return, Exit, the script's
first hotkey/hotstring
label, or the physical end of the script is encountered
(whichever comes first). This top portion of the script is referred to as the
auto-
execute section, but it is really just a subroutine which is
called after program startup.
Note: While the script's first hotkey/hotstring label has the same
effect as return, other
hotkeys and labels do not.
The auto-execute
section is often used to configure settings which apply to every newly launched
thread. For details, see The
Top of the Script.
Subroutines
A subroutine (or sub) is a reusable block of code
which can be called to perform some task.
Scripts use subroutines to define what should happen when a
particular hotkey is pressed or some other event occurs. Scripts can also
call subroutines directly, by using Gosub.
Any label can be
used as the starting point of a subroutine. A subroutine has no explicitly
marked ending point, but instead ends if and
when control is returned to the subroutine's caller by Return or when
the thread is exited. For example:
gosub Label1
Label1:
MsgBox %A_ThisLabel%
return
Note that as labels have no effect when reached during normal
execution, in this example a MsgBox would be shown twice: once while
the subroutine is running and again after it returns.
One important consequence is that you cannot define one subroutine inside
another
subroutine, because the "body" of the inner subroutine
would execute automatically and then return,
effectively terminating the outer
subroutine.
Subroutines should typically be defined separately to any other
block of code, but can also be defined inside a function, allowing the
subroutine access to that function's static variables (and local
variables, but only while the function is running).
Note: Subroutines
defined inside a function have certain limitations regarding the use of local
variables and dynamic variable references, including Gui control variables. For details, see Using Subroutines Within a Function.
User-Defined Functions
Generally speaking, a function is a kind of subroutine. However, within the AutoHotkey
documentation, "subroutine" typically refers to
the kind of subroutine defined by a label (described
above).
User-defined functions differ from subroutines in that they can
accept parameters and return a value, and they can have local variables.
They can be called either by a function call within the script or by the program itself, such as if a
function was passed to the Hotkey or
SetTimer commands.
Functions are defined using
syntax resembling a function call followed by a block of code enclosed in
braces:
MyFunction(FirstParameter, Second,
ByRef Third, Fourth:="")
{
...
return "a value"
}
As with function calls,
there must be no space between the function name and open-parenthesis.
The line break between the close-parenthesis and open-brace is
optional. There can be any amount of whitespace or comments between
the two.
ByRef
indicates that the parameter accepts a variable reference, making that
parameter an alias for whichever variable the caller passes.
If the caller does not pass a variable, the parameter
acts as a normal local variable. ByRef parameters can also be optional.
Optional
parameters are specified by following the parameter name with := or = and a default value, which must be a literal quoted
string, a number, true or false. The operators := and = are interchangeable for
historical reasons, but it is best to use := for consistency with
assignment in expressions.
The function can return a value. If it
does not, the default return value is an empty string.
A function cannot be defined inside another function. Otherwise,
the position of a function definition does not matter; any function
defined within the script can be called from anywhere else.
See Functions for much
more detail.
#Include
The #Include
directive causes the script to behave as though the specified file's contents
are present at this exact position. This is often
used to organise code into separate files, or to make use of
script libraries written by other users.
Note: The following paragraphs detail some common points of
confusion.
When using #Include, it is important to consider what effect the
file's contents would have if placed at that position, since #Include will
have the same effect. For instance:
#Include
generally should not be used in the middle of a subroutine or function.
The use of #Include in the script's auto-execute
section requires special consideration, because the
auto-execute section is
essentially just a subroutine. Execution of a subroutine halts if
it reaches a return, regardless of which file that return is in.
Similarly, if the file contains a hotkey/hotstring, it may be
considered the script's first
hotkey/hotstring, which would act like
return.
The
script only has one auto-execute section, not one
per file.
#Include can be safely used
within the auto-execute section to include files which contain only function definitions, since
function
definitions (but not function calls) are skipped over during
execution. If a file contains other code, one can avoid breaking the auto-
execute section by skipping over the file's contents with Goto.
Unlike in C/C++, #Include does nothing if the file has already
been included by a previous directive. To include the contents of the same
file multiple times, use #IncludeAgain.
Script files containing functions can be automatically included
without having to use #Include, if they are saved in a standard location
and named appropriately. The effect is similar to using #Include
at the end of the main script file. For details, see Libraries of Functions.
Miscellaneous
Dynamic Variables
A dynamic variable reference takes a text value and interprets it as
the name of a variable.
The most common form of dynamic variable reference is called a double reference or double-deref. Before performing a double
reference, the name of the target variable is stored in a second variable.
This second variable can then be used to assign a value to the
target variable indirectly, using a double reference. For example:
target := 42
second := "target"
MsgBox %second%
; Normal (single) variable reference in text => target
MsgBox % second ; Normal (single) variable reference in an
expression => target
MsgBox % %second% ;
Double-deref in an expression => 42
At first, it would appear that percent signs have a different
meaning depending on whether they are used in text or in an expression.
However, it may make more sense to think of %second% as being replaced with the
contents of the variable second in both cases:
MsgBox %second% → MsgBox target: Shows
"target".
MsgBox % %second% → MsgBox % target: Shows
the contents of target, i.e. "42".
Currently, second must
always contain a variable name in the second case; arbitrary expressions are
not supported.
A dynamic variable reference can also take one or more pieces of
literal text and the content of one or more variables, and join them
together to form a single variable name. This is done simply by
writing the pieces of the name and percent-enclosed variables in
sequence, without any spaces. For example, MyArray%A_Index% or MyGrid%X%_%Y%. This is used to access pseudo-arrays, described
below.
For a description of how
dynamic variable references inside functions are resolved, see Functions: More about locals and globals.
Pseudo-arrays
A pseudo-array is actually just a bunch of discrete variables, but
with a naming pattern which allows them to be used like elements of an
array. For example:
MyArray1 = A
MyArray2 = B
MyArray3 = C
Loop 3
MsgBox % MyArray%A_Index% ; Shows
A, then B, then C.
As the individual elements are just normal variables, one can
assign or retrieve a value, but cannot remove or insert elements.
Because
the pseudo-array itself doesn't really exist, it can't be passed
to or returned from a function, or copied as a whole. For these reasons, it is
generally recommended to use normal arrays instead, where possible.
Associative pseudo-arrays
The "index" used to form the final variable name does
not have to be numeric; it could instead be a letter or keyword, making the
pseudo-array similar to an associative array or an object. The
following example creates a pseudo-array with elements "Left",
"Top",
"Right" and "Bottom":
SysGet, WA, MonitorWorkArea
MsgBox, Left: %WALeft% -- Top:
%WATop% -- Right: %WARight% -- Bottom: %WABottom%.
Commands which create
pseudo-arrays
There are several commands
which create associative pseudo-arrays:
GuiControlGet Pos.
RegExMatch, except when given the O) option,
which causes it to output a single object containing all match information.
SysGet Monitor/MonitorWorkArea, as demonstrated above.
StringSplit. New scripts should use StrSplit() instead,
as it creates a normal array.
Caution: These commands
do not follow the same rules as dynamic
variable references. If used within a function, the resulting pseudo-
array is either entirely global or entirely local,
depending only on the first element (or base name) of the array. Some of the
variables in the pseudo-array may be
inaccessible if they are not individually declared. For details, see Functions: More about locals and globals.
AutoHotkey also creates one global pseudo-array to contain any command line parameters that were passed to the script.
Labels
A label identifies a line of code, and can be used as a Goto target
or to form a subroutine. There are three kinds of
label: normal named
labels, hotkey labels
and hotstring labels.
Normal labels consist of a
name followed by a colon.
this_is_a_label:
Hotkey labels consist of a
hotkey followed by double-colon.
^a::
Hotstring labels consist of
a colon, zero or more options, another
colon, an abbreviation and double-colon.
:*:btw::
Generally, aside from
whitespace and comments, no other code can be written on the same line as a
label. However:
A hotkey label can be directly followed by a command or other
statement to create a one-line hotkey. In other words, if a
command, assignment or expression is present on the same line as a
hotkey label, it acts as though followed by return.
A hotkey with a key name written to the right of the double-colon is actually a remapping, which is shorthand for a pair
of
hotkeys. For example, a::b creates hotkeys and labels for *a and *a Up, and does not create a
label named a.
A hotstring with text written to the right of the final
double-colon is an auto-replace hotstring. Auto-replace hotstrings do not act
as labels.
For more details, see Labels.
Software License
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free
Software Foundation, Inc.
51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users. This
General Public License applies to most of the Free
Software Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered
by the GNU Lesser General Public License instead.) You can apply
it to your programs, too.
When we speak of free
software, we are referring to freedom, not price. Our General Public Licenses
are designed to make sure that you have the
freedom to distribute copies of free software (and charge for this service if
you wish), that you receive source code or can get it if you want it, that you can change the software or use
pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you
if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that you
have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software,
and (2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make
certain that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed
on, we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not
reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free program
will individually obtain patent licenses, in effect
making the program proprietary. To prevent this, we have made it clear that any
patent
must be licensed for everyone's free use or not licensed at all.
The precise terms and
conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
MODIFICATION
0. This License applies to any program or other work which
contains a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a
"work based on the
Program" means either the Program or any derivative work
under copyright law: that is to say, a work containing the Program or a
portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is included without
limitation in the term "modification".) Each licensee is
addressed as "you".
Activities other than copying, distribution and modification are
not covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the
Program is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any
warranty; and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Program or any
portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to
carry prominent notices stating that you changed the files and the date of any
change.
b) You must cause any
work that you distribute or publish, that in whole or in part contains or is
derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified
program normally reads commands interactively when run, you must cause it, when
started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but does
not normally print such an announcement, your work based on the
Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, and
can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be
on the terms of this License, whose permissions for other licensees extend to
the
entire whole, and thus to each and every part regardless of who
wrote it.
Thus, it is not the intent of this section to claim rights or
contest your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the
Program with the Program (or with a work based on the Program) on a
volume of a storage or distribution medium does not bring the
other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one
of the following:
a) Accompany it with
the complete corresponding machine-readable source code, which must be
distributed under the terms of
Sections 1 and 2 above on a medium customarily used for software
interchange; or,
b) Accompany it with a
written offer, valid for at least three years, to give any third party, for a
charge no more than your cost of
physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be distributed
under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
c) Accompany it with the
information you received as to the offer to distribute corresponding source
code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such an
offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work
for making modifications to it. For an executable work, complete
source code means all the source code for all modules it contains,
plus any associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However,
as a special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that
component itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent access to
copy the source code from the same place counts as
distribution of the source code, even though third parties are not compelled to
copy
the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights,
from you under this License will not have their licenses terminated so long as
such parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and all
its terms and conditions for copying, distributing or
modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on
the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted
herein. You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement
or otherwise) that contradict the conditions of this License, they do
not excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence
you may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the
Program by all those who receive copies directly or indirectly through you,
then the only way you could satisfy both it and this License would
be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable
under any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply
in other circumstances.
It is not the purpose of this section to induce you to infringe
any patents or other property right claims or to contest validity of any such
claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is implemented by
public license practices. Many people have made generous
contributions to the wide range of software distributed through that system in
reliance on consistent application of that system; it is up to the
author/donor to decide if he or she is willing to distribute software
through any other system and a licensee cannot impose that choice.
This section is intended to
make thoroughly clear what is believed to be a consequence of the rest of this
License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Program under this
License may add an explicit geographical distribution limitation excluding
those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies a version number of this License which applies to it and
"any later version", you have the option of
following the terms and conditions either of that version or of any later
version published by
the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever
published by the Free
Software Foundation.
10. If you wish to incorporate parts of the Program into other
free programs whose distribution conditions are different, write to the
author to ask for permission. For software which is copyrighted by
the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision
will be guided by the two goals of preserving the free status of all
derivatives of
our free software and of promoting the sharing and reuse of
software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT
PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU
ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO
YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN
IF SUCH HOLDER OR OTHER PARTY HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Objects
An object in AutoHotkey is
an abstract datatype which provides three basic functions:
GET a value.
SET a value.
CALL a method (that is, a function which does something with the
target object).
Related topics:
Objects: General
explanation of objects.
Object Protocol:
Specifics about how a script interacts with an object.
IsObject can be used to determine if a value is an object:
Result := IsObject(expression)
Types of objects include:
Object -
scriptable associative array.
File -
provides an interface for file input/output.
Function objects - Func, BoundFunc or user-defined.
ComObject - wraps
an IDispatch interface (a COM or "Automation" object).
Support for objects requires [AHK_L 31+], but some features may
require later a version.
Table of Contents
Basic Usage - Simple Arrays, Associative Arrays, Objects, Freeing Objects, Remarks
Extended Usage - Function References, Arrays of Arrays, Arrays of Functions
Custom Objects - Prototypes, Classes, Construction and Destruction, Meta-Functions
Default Base Object - Automatic Var Init, Pseudo-Properties, Debugging
Implementation - Reference-Counting, Pointers to Objects
Basic Usage
Simple Arrays [v1.1.21+]
Create an array:
Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)
Retrieve an item:
Value := Array[Index]
Assign an item:
Array[Index] := Value
Insert one or more items at
a given index:
Array.InsertAt(Index,
Value, Value2, ...)
Append one or more items:
Array.Push(Value,
Value2, ...)
Remove an item:
RemovedValue := Array.RemoveAt(Index)
Remove the last item:
RemovedValue := Array.Pop()
If the array is not empty, MinIndex and MaxIndex/Length return the lowest and highest index currently in use in the
array. Since the
lowest index is nearly always 1, MaxIndex usually returns the
number of items. However, if there are no integer keys, MaxIndex returns
an empty string whereas Length returns 0. Looping
through an array's contents can be done either by index or with a For-loop. For
example:
array := ["one",
"two", "three"]
; Iterate from 1 to the end of the array:
Loop %
array.Length()
MsgBox % array[A_Index]
; Enumerate the array's contents:
For
index, value in array
MsgBox % "Item " index " is '" value "'"
Associative Arrays
[v1.1.21+]
An associative array is an object which contains a collection of
unique keys and a collection of values, where each key is associated with
one value. Keys can be strings, integers or objects,
while values can be of any type. An associative array can be created as
follows:
Array := {KeyA: ValueA, KeyB:
ValueB, ..., KeyZ: ValueZ}
Array := Object("KeyA",
ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)
Using the {key:value}
notation, quote marks are optional for keys which consist only of word
characters. Any expression can be used as a key, but to use a variable as a key, it must be enclosed
in parentheses. For example, {(KeyVar): Value} and {GetKey(): Value} are
both valid.
Retrieve an item:
Value := Array[Key]
Assign an item:
Array[Key] := Value
Remove an item:
RemovedValue := Array.Delete(Key)
Enumerating items:
array := {ten: 10, twenty: 20, thirty: 30}
For key,
value in array
MsgBox %key% = %value%
Associative arrays can be
sparsely populated - that is, {1:"a",1000:"b"} contains only two key-value pairs, not 1000.
In AutoHotkey v1.x, simple arrays and associative arrays are the
same thing. However, treating [] as a
simple linear array helps to keep its role
clear, and improves the chance of your script working with a future version of
AutoHotkey, which might differentiate between
simple arrays and associative arrays.
Objects [AHK_L 31+]
For all types of objects, the notation Object.LiteralKey can be
used to access a property, array element or method, where LiteralKey
is
an identifier or integer and Object is any
expression. Identifiers are unquoted strings which may consist of alphanumeric
characters,
underscore and, in [v1.1.09+], non-ASCII characters. For example, match.Pos is equivalent to match["Pos"] while arr.1 is equivalent
to arr[1]. There must be no space after the dot.
Examples:
Retrieve a property:
Value := Object.Property
Set a property:
Object.Property := Value
Call a method:
ReturnValue := Object.Method(Parameters)
Call a method with a computed method name:
ReturnValue :=
Object[MethodName](Parameters)
Some properties of COM
objects and user-defined objects can accept parameters:
Value := Object.Property[Parameters]
Object.Property[Parameters] := Value
Related: Object, File Object, Func Object, COM object
Known limitation:
Currently x.y[z]() is
treated as x["y",
z](), which is not supported. As a workaround, (x.y)[z]() evaluates x.y first, then
uses the result as the target of the method call. Note that x.y[z].Call() does not have this
limitation since it is evaluated the same
as (x.y[z]).Call().
Freeing Objects
Scripts do not free objects explicitly. When the last reference to
an object is released, the object is freed automatically. A reference stored
in a variable is released automatically when that
variable is assigned some other value. For example:
obj := {} ; Creates an object.
obj := "" ; Releases the last reference, and therefore
frees the object.
Similarly, a reference stored in a field of another object is
released when that field is assigned some other value or removed from the
object. This also applies to arrays, which are actually objects.
arr := [{}] ;
Creates an array containing an object.
arr[1] := {} ; Creates a
second object, implicitly freeing the first object.
arr.RemoveAt(1) ; Removes
and frees the second object.
Because all references to an object must be released before the
object can be freed, objects containing circular references aren't freed
automatically. For instance, if
x.child refers to y and y.parent refers to x, clearing x and y is not sufficient since
the parent object still contains a
reference to the child and vice versa. To resolve this situation, remove the
circular reference.
x := {}, y := {} ; Create two objects.
x.child := y, y.parent := x ; Create a circular reference.
y.parent := "" ; The circular reference must be
removed before the objects can be freed.
x := "", y := "" ; Without the above line, this
would not free the objects.
For more advanced usage and details, see Reference Counting.
Remarks
Syntax
All types of objects support both array syntax (brackets) and
object syntax (dots).
Additionally, object references can themselves be used in
expressions:
When an object reference is compared with some other value using =, ==, != or <>, they
are considered equal only if both values
are references to the same object.
Objects are always considered true when a boolean value is
required, such as in if obj, !obj or obj ? x : y.
An object's address can be retrieved using the &address-of operator. This uniquely identifies the object from the
point of its
creation to the moment its last reference is released.
If an object is used in any context where an object is not
expected, it is treated as an empty string. For example, MsgBox %object% shows
an empty MsgBox and
object + 1 yields an empty string. Do
not rely on this behaviour as it may change.
When a method-call is followed immediately by an assignment
operator, it is equivalent to setting a property with parameters. For
example, the following are equivalent:
obj.item(x) := y
obj.item[x] := y
Compound assignments such
as x.y += 1 and --arr[1] are supported.
[v1.1.20+]: Parameters can be omitted when getting or setting
properties. For example, x[,2]. Scripts can utilize this by defining default
values for parameters in properties and meta-functions. The
method name can also be completely omitted, as in x[](a). Scripts can
utilize this by defining a default value for the __Call meta-function's first parameter,
since it is not otherise supplied with a value. Note
that this differs from x.(a), which
is equivalent to x[""](a). If the property or method name is omitted when invoking a COM
object,
its "default member" is invoked.
Keys
Some limitations apply to
which values can be used as keys in objects created with [], {} or the new operator:
Integer
keys are stored using the native signed integer type. AutoHotkey 32-bit
supports integer keys in the range -2147483648 to
2147483647. AutoHotkey supports 64-bit integers, but only
AutoHotkey 64-bit supports the full range as keys in an object.
As a consequence of the point above, the string format of integer
values is not retained. For example, x[0x10], x[16] and
x[00016] are equivalent. This also applies to numeric strings which don't
have a decimal point.
Quoted literal strings are considered purely non-numeric in v1.x,
so x[1] and x["1"] are not equivalent.
Additionally, if a quoted
literal string is concatenated with another value (as in "0x"
x), the result is treated as purely non-numeric. However, this does
not
apply to variables, so x[1] and x[y:="1"] are equivalent. This issue
will be resolved in AutoHotkey v2, so scripts should avoid
using quoted numeric literals as keys.
Floating-point numbers are not supported as keys - instead they
are converted to strings. In v1.x, floating-point literals retain their
original format
whereas pure floating-point numbers (such as the result of 0+1.0 or Sqrt(y)) are forced into the current float
format. For consistency and clarity, scripts should avoid
using floating-point literals as keys.
By default, the string key "base" corresponds to the
object's base property, so cannot be used for storing ordinary values with a
normal assignment. However, any property can be overridden by
storing a value by some other means, such as
ObjRawSet(Object,
"base", "") or Object.SetCapacity("base",
0). Once this is done, the key "base" acts like any other
string.
Although built-in method names
such as "Length" can be used as keys, storing a value will prevent
the corresponding method from
being called (unless that value is a reference to the appropriate
function, such as ObjLength).
Extended Usage
Function References
[v1.1.00+]
If the variable func contains a function name, the function can be
called one of two ways: %func%() or func.(). However, this requires the function
name to be resolved each time, which is inefficient if the function is called
more than once. To improve performance, the
script can retrieve a reference to the function and store it for
later use:
Func := Func("MyFunc")
A function can be called by
reference using the following syntax:
RetVal := %Func%(Params)
; Requires [v1.1.07+]
RetVal := Func.Call(Params) ; Requires [v1.1.19+]
RetVal := Func.(Params)
; Not recommended
For details about additional properties of function references,
see Func Object.
Arrays of Arrays
AutoHotkey supports "multi-dimensional" arrays by
transparently storing arrays inside other arrays. For example, a table could be
represented as an array of rows, where each row is itself an array
of columns. In that case, the content of column y of row x can be
set
using either of the methods below:
table[x][y] := content ; A
table[x, y] := content ; B
If table[x] does not exist, A and B differ in two ways:
A fails
whereas B automatically creates an object and stores it in table[x].
If table's base defines meta-functions, they are invoked as follows:
table.base.__Get(table, x)[y] := content ; A
table.base.__Set(table, x, y, content) ; B
Consequently, B allows the object to define custom behaviour for
the overall assignment.
Multi-dimensional assignments such as table[a, b, c, d] := value are handled as follows:
If there
is only one key remaining, perform the assignment and return. Otherwise:
Search the object for the first key in the list.
If a non-object is found, fail.
If an object is not found, create one and store it.
Recursively invoke the sub-object, passing the remaining keys and
value - repeat from the top.
This behaviour only applies to script-created objects, not more
specialized types of objects such as COM objects or COM arrays.
Arrays of Functions
An array of functions is
simply an array containing function names or references. For example:
array :=
[Func("FirstFunc"), Func("SecondFunc")]
; Call each function, passing "foo" as a parameter:
Loop 2
array[A_Index].Call("foo")
; Call each function, implicitly passing the array itself as a
parameter:
Loop 2
array[A_Index]()
FirstFunc(param) {
MsgBox % A_ThisFunc ": " (IsObject(param) ? "object"
: param)
}
SecondFunc(param) {
MsgBox % A_ThisFunc ": " (IsObject(param) ? "object"
: param)
}
For backward-compatibility, the second form will not pass array as a parameter if array[A_Index] contains a function name instead of a function reference. However, if array[A_Index] is inherited from array.base[A_Index], array will be passed as a parameter.
Custom Objects
Objects created by the
script do not need to have any predefined structure. Instead, each object can
inherit properties and methods from
its base object (otherwise known as
a "prototype" or "class"). Properties and methods can also
be added to (or removed from) an object at any time, and those changes will affect any and all derived
objects. For more complex or specialized situations, a base object can override
the standard behaviour of any objects derived from it
by defining meta-functions.
Base objects are just
ordinary objects, and are typically created one of two ways:
class baseObject {
static foo :=
"bar"
}
; OR
baseObject := {foo: "bar"}
To create an object derived
from another object, scripts can assign to the base property or use the new keyword:
obj1 := Object(), obj1.base := baseObject
obj2 := {base: baseObject}
obj3 := new baseObject
MsgBox % obj1.foo " "
obj2.foo " " obj3.foo
It is possible to reassign an object's base at any time, effectively replacing all of the properties and
methods that the object inherits.
Prototypes
Prototype or base objects are constructed
and manipulated the same as any other object. For example, an ordinary object
with one
property and one method might be constructed like this:
; Create an object.
thing := {}
; Store a value.
thing.foo := "bar"
; Create a method by storing a function reference.
thing.test := Func("thing_test")
; Call the method.
thing.test()
thing_test(this) {
MsgBox % this.foo
}
When thing.test() is
called, thing is automatically inserted at the beginning of the parameter list.
However, for backward-
compatibility, this does not occur when a function is stored by
name (rather than by reference) directly in the object (rather than being
inherited from a base object). By convention, the function is
named by combining the "type" of object and the method name.
An object is a prototype or base if another object derives from it:
other := {}
other.base := thing
other.test()
In this case, other inherits foo
and test from thing. This inheritance is dynamic, so if thing.foo is modified, the change
will be reflected by other.foo. If the script assigns to other.foo, the value is stored in
other and any further changes to thing.foo will have no effect
on other.foo. When other.test() is
called, its this parameter contains a reference to other instead of thing.
Classes [v1.1.00+]
At its root, a "class" is a set or category of things
having some property or attribute in common. Since a base or prototype object defines
properties and behaviour for set of objects, it can also be called
a class object. For convenience, base objects can be defined using the
"class" keyword as shown below:
class ClassName extends
BaseClassName
{
InstanceVar :=
Expression
static ClassVar :=
Expression
class NestedClass
{
...
}
Method()
{
...
}
Property[] ; Brackets are optional
{
get {
return ...
}
set {
return ... := value
}
}
}
When the script is loaded, this constructs an object and stores it
in the global (or [in v1.1.05+] super-global)
variable ClassName. To
reference this class inside a force-local function (or an assume-local or assume-static function prior to [v1.1.05]), a declaration such as
global ClassName is required. If extends
BaseClassName is present, BaseClassName must be the full name
of another class (but as of [v1.1.11],
the order that they are defined in does not matter). The full name of each
class is stored in object.__Class.
Because the class is referenced via a variable, the class name
cannot be used to both reference the class and create a separate variable
(such as to hold an instance of the class) in the same context.
For example, box := new Box would replace the class
object in Box with an
instance of itself. [v1.1.27+]: #Warn ClassOverwrite enables a warning to be shown at load time for each
attempt to overwrite a class.
Within this documentation, the word "class" on its own
usually means a class object constructed with the class keyword.
Class definitions can contain variable declarations, method
definitions and nested class definitions.
Instance Variables
[v1.1.01+]
An instance variable is
one that each instance of the class (that is, each object derived from the
class) has its own copy of. They are
declared like normal assignments, but the this. prefix is omitted (only directly within the class body):
InstanceVar := Expression
These declarations are evaluated each time a new instance of the
class is created with the new keyword. The method name __Init is
reserved for this purpose, and should not be used by the script.
The __New() method
is called after all such declarations have been
evaluated, including those defined in base classes. Expression can
access other instance variables and methods via this, but all other
variable references are assumed to be global.
To access an instance
variable (even within a method), always specify the target object; for example,
this.InstanceVar.
[v1.1.08+]: Declarations like x.y := z are also supported, provided that x was previously declared in this class. For example, x := {}, x.y :=
42 declares x and also
initializes this.x.y.
Static/Class Variables
[v1.1.00.01+]
Static/class variables belong to the class itself, but can be
inherited by derived objects (including sub-classes). They are declared like
instance variables, but using the static keyword:
static ClassVar := Expression
Static declarations are evaluated only once, before the auto-execute section, in the order they appear in the script. Each declaration stores
a value in the class object. Any variable references
in Expression are assumed to be global.
To assign to a class variable, always specify the class object;
for example, ClassName.ClassVar := Value. If an
object x is derived
from ClassName and x itself does not contain the key
"ClassVar", x.ClassVar may also
be used to dynamically retrieve the value of
ClassName.ClassVar. However, x.ClassVar := y would
store the value in x, not in ClassName.
[v1.1.08+]: Declarations like static x.y := z are also supported, provided that x was previously declared in this class. For example,
static x := {}, x.y := 42 declares x and also initializes ClassName.x.y.
Nested Classes
Nested class definitions allow a class object to be stored inside
another class object rather than a separate global variable. In the example
above, class NestedClass constructs an object and stores it in ClassName.NestedClass.
Sub-classes could inherit NestedClass or
override it with their own nested class (in which case new
this.NestedClass could be used to instantiate whichever class is
appropriate).
class NestedClass
{
...
}
Methods
Method definitions look identical to function definitions. Each
method has a hidden parameter named this, which typically contains
a
reference to an object derived from the class. However, it could
contain a reference to the class itself or a derived class, depending on
how the method was called. Methods are stored by reference in the class object.
Method()
{
...
}
Inside a method, the pseudo-keyword base can be used to access the
super-class versions of methods or properties which are overridden
in a derived class. For example, base.Method() in the class defined above
would call the version of Method which is defined by
BaseClassName. Meta-functions are not called; otherwise, base.Method() behaves like BaseClassName.Method.Call(this). That is,
base.Method() always invokes the base of the class where the current method was
defined, even if this is derived from a sub-
class of that class or some other class entirely.
base.Method() implicitly passes this as the first (hidden)
parameter.
base only has special meaning if followed by a dot . or
brackets [], so code like obj :=
base, obj.Method() will not work. Scripts
can disable the special behaviour of base by assigning it a non-empty value; however, this is not
recommended. Since the variable base must be
empty, performance may be reduced if the script omits #NoEnv.
Properties [v1.1.16+]
Property definitions allow
a method to be executed whenever the script gets or sets a specific key.
Property[]
{
get {
return ...
}
set {
return ... := value
}
}
Property is simply the name of the property, which will be used to
invoke it. For example, obj.Property would
call get while
obj.Property := value would call set. Within get or
set, this refers to the object being invoked. Within set, value contains the value being
assigned.
Parameters can be passed by enclosing them in square brackets to
the right of the property name, both when defining the property and
when calling it. Aside from using square brackets, parameters of
properties are defined the same way as parameters of methods -
optional, ByRef and variadic parameters are supported.
The return value of get or set
becomes the result of the sub-expression which invoked the property. For
example, val := obj.Property := 42 stores the return value of set in val.
Each class can define one or both halves of a property. If a class
overrides a property, it can use base.Property to
access the property
defined by its base class. If get or set is not defined, it can be handled by a base class. If set
is not defined and is not handled by a meta- function or base class, assigning a value stores it in the
object, effectively disabling the property.
Internally, get and set are
two separate methods, so cannot share variables (except by storing them in this).
Meta-functions provide a broader way of
controlling access to properties and methods of an object, but are more
complicated and error- prone.
Construction and
Destruction
Whenever a derived object is created with the new keyword [requires
v1.1.00+], the __New method defined by its base object is called.
This method can accept parameters, initialize the object and
override the result of the new operator by returning a
value. When an object is destroyed, __Delete is called. For example:
m1 := new GMem(0, 20)
m2 := {base: GMem}.__New(0, 30)
class GMem
{
__New(aFlags, aSize)
{
this.ptr :=
DllCall("GlobalAlloc", "UInt", aFlags, "Ptr",
aSize, "Ptr")
if !this.ptr
return ""
MsgBox % "New
GMem of " aSize " bytes at address " this.ptr "."
return this ; This line can be omitted when using the
'new' operator.
}
__Delete()
{
MsgBox %
"Delete GMem at address " this.ptr "."
DllCall("GlobalFree", "Ptr", this.ptr)
}
}
__Delete is not called for
any object which has the key "__Class". Class
objects have this key by default.
[v1.1.28+]: If an exception or runtime error is thrown while
__Delete is executing and is not handled within __Delete, it acts as though
__Delete was called from a new thread. That
is, an error dialog is displayed and __Delete returns, but the thread does not
exit (unless it
was already exiting). Prior to v1.1.28, unhandled exceptions
caused inconsistent behavior.
Meta-Functions
Method syntax:
class ClassName {
__Get([Key, Key2, ...])
__Set([Key, Key2, ...],
Value)
__Call(Name [,
Params...])
}
Function syntax:
MyGet(this [, Key, Key2, ...])
MySet(this [, Key, Key2, ...], Value)
MyCall(this, Name [, Params...])
ClassName := { __Get: Func("MyGet"), __Set:
Func("MySet"), __Call: Func("MyCall")
}
Meta-functions define what
happens when a key is requested but not found within the target object. For
example, if obj.key has not been assigned a
value, it invokes the __Get meta-function. Similarly, obj.key
:= value invokes __Set and obj.key() invokes __Call. These
meta-functions (or methods) would need to be defined
in obj.base, obj.base.base or such.
When the script gets, sets
or calls a key which does not exist within the target object, the base object
is invoked as follows:
If this
base object defines the appropriate meta-function, call it. If the meta-function explicitly returns, use
the return value as the
result of the operation (whatever caused the meta-function to be
called) and return control to the script. Otherwise, continue as
described below.
Set: If the meta-function handled an assignment, it should return
the value which was assigned. This allows assignments to be
chained, as in a.x :=
b.y := z. The return value may differ from the original
value of z (for instance, if restrictions are imposed
on which values can be assigned).
Search
for a matching key in the base object's own fields.
[v1.1.16+]: If a key corresponding to a property is found and it
implements get or set (as
appropriate), invoke the property and
return. If this is a method call, invoke get.
If no key was found, recursively invoke this base object's own
base (apply each of these steps to it, starting at the top of this list). If
we're not finished yet, search this base object for a matching key
again in case one was added by a meta-function.
Due to
backward-compatibility, this step is performed for set operations even if a key
was found (unless it defines a property
which implements set).
If multiple parameters were given for get or set and a key was found, check its value.
If that value is an object, handle the
remaining parameters by invoking it, and do nothing further.
If a key
was found,
Get: Return the value.
Call: Attempt to call the value, passing the target object as the
first parameter (this). The value should be a
function name or a
function object.
If a meta-function stores a matching key in the object but does
not return, the behaviour is the same as if the key initially existed in the
object. For an example using __Set, see Sub-classing Arrays of Arrays.
If the operation still
hasn't been handled, check if this is a built-in method or property:
Get: If the key is "base", return the object's base.
Set: If the key is "base", set the object's base (or
remove it if the value isn't an object).
Call: Call a built-in method if
applicable.
If the operation still
hasn't been handled,
Get and Call: Return an empty string.
Set: If only one key parameter was given, store the key and value
in the target object and return the assigned value. If multiple
parameters were given, create a new object and store it using the
first parameter as a key, then handle the remaining parameters by
invoking the new object. (See Arrays of
Arrays.)
Known limitation:
Using return without
a value is equivalent to return "". This may be changed in a future version so that return can be
used to
"escape" from a meta-function without overriding the
default behaviour.
Dynamic Properties
Property syntax can be used to define properties which compute a value each time
they are evaluated, but each property must be known in advance and defined individually in the script. By
contrast, __Get and __Set can be used to implement properties which aren't
known by the script.
For example, a
"proxy" object could be created which sends requests for properties
over the network (or through some other channel). A remote server would send back a response containing the
value of the property, and the proxy would return the value to its caller. Even
if the name of each property was known in
advance, it would not be logical to define each property individually in the
proxy class since
every property does the same thing (send a network request).
Meta-functions receive the property name as a parameter, so are a good
solution for this problem.
Another use of __Get and
__Set is to implement a set of related properties which share code. In the
example below they are used to
implement a "Color" object with R, G, B and RGB
properties, where only the RGB value is actually stored:
red := new Color(0xff0000), red.R -= 5
cyan := new Color(0), cyan.G :=
255, cyan.B := 255
MsgBox % "red: " red.R "," red.G ","
red.B " = " red.RGB
MsgBox % "cyan: " cyan.R "," cyan.G
"," cyan.B " = " cyan.RGB
class Color
{
__New(aRGB)
{
this.RGB := aRGB
}
static Shift := {R:16, G:8, B:0}
__Get(aName)
{
;
NOTE: Using this.Shift here would cause an infinite loop!
shift :=
Color.Shift[aName] ; Get the number of bits to shift.
if (shift !=
"") ; Is it a known property?
return (this.RGB >> shift)
& 0xff
; NOTE: Using 'return' here would break
this.RGB.
}
__Set(aName, aValue)
{
if ((shift := Color.Shift[aName]) !=
"")
{
aValue &= 255 ; Truncate it to the proper range.
; Calculate and store the new RGB
value.
this.RGB := (aValue << shift)
| (this.RGB & ~(0xff << shift))
; 'Return' must
be used to indicate a new key-value pair should not be created.
; This also
defines what will be stored in the 'x' in 'x := clr[name] := val':
return aValue
}
; NOTE: Using 'return'
here would break this.stored_RGB and this.RGB.
}
; Meta-functions can be
mixed with properties:
RGB {
get {
; Return it in
hex format:
return
format("0x{:06x}", this.stored_RGB)
}
set {
return this.stored_RGB := value
}
}
}
However, in this case Property syntax could have been used
instead, where code is shared by simply having each property call a central
method. It is better to
avoid using meta-functions where possible due to the high risk of misuse (see
the notes in red above).
Objects as Functions
For an outline of how to
create objects which can act as functions, see
Function Objects.
A function object can also act as a meta-function, such as to
define dynamic properties similar to those in the previous section. Although
it is recommended to use property syntax
instead, the example below shows the potential of meta-functions for
implementing new
concepts or behaviour, or changing the structure of the script.
blue := new Color(0x0000ff)
MsgBox % blue.R ","
blue.G "," blue.B
class Properties extends FunctionObject
{
Call(aTarget, aName, aParams*)
{
; If
this Properties object contains a definition for this half-property, call it.
if ObjHasKey(this,
aName)
return this[aName].Call(aTarget,
aParams*)
}
}
class Color
{
__New(aRGB)
{
this.RGB := aRGB
}
class __Get extends Properties
{
R() {
return (this.RGB
>> 16) & 255
}
G() {
return (this.RGB
>> 8) & 255
}
B() {
return this.RGB & 255
}
}
;...
}
Sub-classing Arrays of
Arrays
When a multi-parameter assignment such as table[x, y] := content implicitly causes a new object to be created, the new object
ordinarily has no base and therefore no custom methods or special
behaviour. __Set may be used to initialize these objects, as
demonstrated below.
x := {base: {addr:
Func("x_Addr"), __Set: Func("x_Setter")}}
; Assign value, implicitly calling x_Setter to create sub-objects.
x[1,2,3] := "..."
; Retrieve value and call example
method.
MsgBox % x[1,2,3] "`n"
x.addr() "`n" x[1].addr() "`n" x[1,2].addr()
x_Setter(x, p1, p2, p3) {
x[p1] := new x.base
}
x_Addr(x) {
return &x
}
Since x_Setter has four mandatory parameters, it will only be called when there
are two or more key parameters. When
the assignment above occurs, the following takes
place:
x[1] does not exist, so x_Setter(x,1,2,3) is called ("..." is not
passed as there are too few parameters).
x[1] is assigned a new object with the same base as x.
No value is returned – the assignment continues.
x[1][2] does not exist, so x_Setter(x[1],2,3,"...") is called.
x[1][2] is assigned a new object with the same base as x[1].
No value is returned – the assignment continues.
x[1][2][3] does not exist, but since x_Setter requires four parameters
and there are only three (x[1][2], 3, "..."), it is not
called and the assignment completes as normal.
Default Base Object
When a non-object value is used with object syntax, the default
base object is invoked. This can be
used for debugging or to globally
define object-like behaviour for strings, numbers and/or
variables. The default base may be
accessed by using .base with any non-object
value; for instance, "".base. Although the default base cannot be set as in "".base
:= Object(), the default base may itself have a base
as in "".base.base
:= Object().
Automatic Var Init
When an empty variable is used as the target of a set operation, it is passed directly to
the __Set meta-function, giving it opportunity to
insert a new
object into the variable. For
brevity, this example does not support multiple parameters; it could, by using
a variadic
function.
"".base.__Set :=
Func("Default_Set_AutomaticVarInit")
empty_var.foo := "bar"
MsgBox % empty_var.foo
Default_Set_AutomaticVarInit(ByRef
var, key, value)
{
if (var = "")
var := Object(key, value)
}
Pseudo-Properties
Object "syntax
sugar" can be applied to strings and numbers.
"".base.__Get :=
Func("Default_Get_PseudoProperty")
"".base.is :=
Func("Default_is")
MsgBox % A_AhkPath.length " == " StrLen(A_AhkPath)
MsgBox % A_AhkPath.length.is("integer")
Default_Get_PseudoProperty(nonobj,
key)
{
if (key =
"length")
return
StrLen(nonobj)
}
Default_is(nonobj, type)
{
if nonobj is %type%
return true
return false
}
Note that built-in
functions may also be used, but in this case the parentheses cannot be omitted:
"".base.length :=
Func("StrLen")
MsgBox % A_AhkPath.length() "
== " StrLen(A_AhkPath)
Debugging
If allowing a value to be
treated as an object is undesirable, a warning may be shown whenever a
non-object value is invoked:
"".base.__Get := "".base.__Set :=
"".base.__Call := Func("Default__Warn")
empty_var.foo := "bar"
x := (1 +
1).is("integer")
Default__Warn(nonobj,
p1="", p2="", p3="", p4="")
{
ListLines
MsgBox A non-object value was improperly invoked.`n`nSpecifically:
%nonobj%
}
Implementation
Reference-Counting
AutoHotkey uses a basic reference-counting mechanism to
automatically free the resources used by an object when it is no longer
referenced by the script. Script authors should not invoke this
mechanism explicitly, except when dealing directly with unmanaged
pointers to objects.
Currently in AutoHotkey v1.1, temporary references created within
an expression (but not stored anywhere) are released immediately
after use. For example, Fn(&{}) passes an invalid address to the function, because
the temporary reference returned by {} is
released
immediately after the address-of operator is evaluated.
To run code when the last reference to an object is being
released, implement the __Delete meta-function.
Known Limitations:
Circular
references must be broken before an object can be freed. For details and an
example, see Freeing Objects.
Although references in static and global variables are released
automatically when the program exits, references in non-static local
variables or on the expression evaluation stack are not. These references are only released if the
function or expression is allowed
to complete normally.
Although memory used by the
object is reclaimed by the operating system when the program exits, __Delete will not be called unless
all
references to the object are freed. This can be
important if it frees other resources which are not automatically reclaimed by
the operating system, such as temporary files.
Pointers to Objects
In some rare cases it may
be necessary to pass an object to external code via DllCall or store it in a
binary data structure for later
retrieval. An object's address can be retrieved via address
:= &object; however, this effectively makes two references
to the object, but the program only knows about the
one in object. If the last known reference to the object was released, the
object would be deleted.
Therefore, the script must inform the object that it has gained a
reference. There are two ways to do this:
; Method #1: Explicitly increment the reference count.
address := &object
ObjAddRef(address)
; Method #2: Use Object(), which increments the reference count
and returns an address.
address := Object(object)
This function can also be
used to convert an address back into a reference:
object := Object(address)
Either way, the script must
also inform the object when it is finished with that reference:
; Decrement the object's reference count to allow it to be freed:
ObjRelease(address)
Generally each new copy of an object's address should be treated
as another reference to the object, so the script should call ObjAddRef
when it gains a copy and ObjRelease immediately
before losing one. For example, whenever an address is copied via something
like x
:= address, ObjAddRef should be
called. Similarly, when the script is finished with x (or is about to overwrite x's value), it should call
ObjRelease.
Note that the Object()
function can be used even on objects which it did not create, such as COM objects and File objects.
Using the Program
AutoHotkey doesn't do anything on its own; it needs a script to
tell it what to do. A script is simply a plain text file with the .ahk
filename extension containing instructions for the program, like a
configuration file, but much more powerful. A script can do as little as
performing a single action and then exiting, but most
scripts define a number of hotkeys,
with each hotkey followed by one or more
actions to take when the hotkey is pressed.
#z::Run https://autohotkey.com ; Win+Z
^!n:: ; Ctrl+Alt+N
if WinExist("Untitled - Notepad")
WinActivate
else
Run Notepad
return
Tip: If your browser
supports it, you can download any code block (such as the one above) as a
script file by clicking the button which
appears in the top-right of the code block when you hover your
mouse over it.
Table of Contents
Create a Script
Edit a Script
Run a Script
Tray Icon
Main Window
Command Line Usage
Portability of AutoHotkey.exe
Installer Options
Run with UI Access
Create a Script
There are a couple of
common ways to create a script file:
In
Notepad (or a text editor of your choice), save a file with the .ahk filename extension. On some systems you may need to
enclose the name in quotes to ensure the editor does not add
another extension (such as .txt).
Be sure
to save the file as UTF-8 with BOM if it will contain non-ASCII characters. For
details, see the FAQ.
In Explorer, right-click in empty space in the folder where you
want to save the script, then select New and AutoHotkey Script.
You can then type a name for the script (taking care not to erase
the .ahk extension if it is
visible).
See Scripting Language for
details about how to write a script.
Edit a Script
To open a script for editing, right-click on the script file and
select Edit Script. If the script is already running, you can use the Edit
command or right-click the script's tray
icon and select Edit
This Script. By default this will
open Notepad, but that can be changed by writing to the registry as shown here. Of
course, you can always open your text editor first and then open the script as
you would any
other text file.
After editing a script, you must run or reload the
script for the changes to take effect. A running script can usually be reloaded
via its tray
menu.
Run a Script
With AutoHotkey installed,
there are several ways to run a script:
Double-click a script file (or shortcut to a script file) in
Explorer.
Call AutoHotkey.exe on the command line and pass the script's
filename as a command-line parameter.
After creating the default script, launch
AutoHotkey via the shortcut in the Start menu to run it.
If AutoHotkey is pinned to the taskbar or Start menu on Windows 7
or later, recent or pinned scripts can be launched via the
program's Jump List.
Most scripts have an effect only while they are running. Use the tray menu or the ExitApp command
to exit a script. Scripts are also
forced to exit when Windows shuts down. To configure a script to
start automatically after the user logs in, the easiest way is to place a
shortcut to the script file in the Startup folder.
Scripts can also be compiled; that is, combined
together with an AutoHotkey binary file to form a self-contained executable
(.exe) file.
Tray Icon
By default, each script
adds its own icon to the taskbar notification area (commonly known as the
tray).
The tray icon usually looks like this (but the color or letter
changes when the script is paused or suspended):
Right-click the tray icon to show the tray menu, which has the
following options by default:
Open -
Open the script's main window.
Help - Open the AutoHotkey offline help file.
Window Spy - Displays various information about a window.
Reload This Script - See Reload.
Edit This Script - See Edit.
Suspend Hotkeys - Suspend or
unsuspend hotkeys.
Pause Script - Pause or unpause the script.
Exit - Exit the script.
By default, double-clicking the tray icon shows the script's main
window.
The Menu command can be used to customise the tray icon and menu.
The #NoTrayIcon
directive can be used to hide the tray icon.
Main Window
The script's main window is usually hidden, but can be shown via
the tray
icon or one of the commands listed below to gain
access to
information useful for debugging the script. Items under the View menu control what the main window
displays:
Lines most recently executed - See ListLines.
Variables and their contents - See ListVars.
Hotkeys and their methods - See
ListHotkeys.
Key history and script info - See KeyHistory.
Known issue: Keyboard shortcuts
for menu items do not work while the script is displaying a MsgBox or other
dialog.
The built-in variable A_ScriptHwnd contains
the unique ID (HWND) of the script's main window.
Closing this window with WinClose (even
from another script) causes the script to exit, but most other methods just
hide the window
and leave the script running.
Command Line Usage
See Passing Command Line Parameters to a Script for
command line usage, including a list of command line switches which affect the
program's behavior.
Portability of AutoHotkey.exe
The file AutoHotkey.exe is
all that is needed to launch any .ahk script.
[AHK_L 51+]: Renaming AutoHotkey.exe also changes which script it
runs by default, which can be an alternative to compiling a script
for use on a computer without AutoHotkey installed.
For instance, MyScript.exe automatically runs MyScript.ahk if a filename is not
supplied, but is also capable of running other scripts.
Installer Options
To silently install AutoHotkey into the default directory (which
is the same directory displayed by non-silent mode), pass the parameter
/S to the installer. For example:
AutoHotkey110800_Install.exe /S
A directory other than the default may be specified via the /D
parameter (in the absence of /S, this changes the default directory
displayed by the installer). For example:
AutoHotkey110800_Install.exe /S
/D=C:\Program Files\AutoHotkey
Version: If AutoHotkey
was previously installed, the installer automatically detects which version of
AutoHotkey.exe to set as the
default. Otherwise, the default is Unicode 32-bit or Unicode
64-bit depending on whether the OS is 64-bit. To override which version of
AutoHotkey.exe is set as
the default, pass one of the following switches:
/A32 or /ANSI: ANSI 32-bit.
/U64 or /x64: Unicode 64-bit (only
valid on 64-bit systems).
/U32: Unicode 32-bit.
For example, the following
installs silently and sets ANSI 32-bit as the default:
AutoHotkey110800_Install.exe /S
/A32
Uninstall: To silently
uninstall AutoHotkey, pass the /Uninstall
parameter to Installer.ahk. For example:
"C:\Program Files\AutoHotkey\AutoHotkey.exe"
"C:\Program Files\AutoHotkey\Installer.ahk" /Uninstall
For AutoHotkey versions older than 1.1.08.00,
use uninst.exe /S. For example:
"C:\Program
Files\AutoHotkey\uninst.exe" /S
Note: Installer.ahk must be run as admin to work correctly.
Extract: Later versions of the installer include a link in the
bottom-right corner to extract setup files without installing. If this function
is
present, the /E switch can be used to invoke it from the command line. For
example:
AutoHotkey110903_Install.exe
/D=F:\AutoHotkey /E
Restart scripts [v1.1.19.02+]: In silent install/uninstall mode,
running scripts are closed automatically, where necessary. Pass the /R
switch to automatically reload these scripts using whichever EXE
they were running on, without command line args. Setup will attempt
to launch the scripts via Explorer, so they do not
run as administrator if UAC is enabled.
Taskbar buttons [v1.1.08+]: On Windows 7 and later, taskbar
buttons for multiple scripts are automatically grouped together or
combined into one button by default. The Separate taskbar buttons
option disables this by registering each AutoHotkey executable as a
host app (IsHostApp).
[v1.1.24.02+]: For
command-line installations, specify /IsHostApp or /IsHostApp=1 to enable the option and /IsHostApp=0 to disable
it.
Run with UI Access
[v1.1.24.02+]
The installer GUI has an option "Add 'Run with UI Access' to
context menus". This context menu option provides a workaround for
common UAC-related issues by allowing the script to automate administrative programs -
without the script running as admin. To
achieve this, the installer does the following:
Copies AutoHotkeyA32.exe, AutoHotkeyU32.exe and (if present)
AutoHotkeyU64.exe to AutoHotkey*_UIA.exe.
Sets the uiAccess attribute in each
UIA file's embedded manifest.
Creates a self-signed digital certificate named
"AutoHotkey" and signs each UIA file.
Registers the context menu option to run the appropriate exe file.
If any these UIA files are present before installation, the
installer will automatically update them even if the UI Access option is not
enabled.
For command-line installations, specify /uiAccess or /uiAccess=1 to enable the option and /uiAccess=0 to disable it. By default, the installer will enable the option if UAC is enabled and the
UI Access context menu option was present before installation.
Scripts which need to run other scripts with UI access can simply Run the
appropriate UIA.exe file with the normal command
line
parameters.
Known limitations:
UIA is
only effective if the file is in a trusted location; i.e. a Program Files
sub-directory.
UIA.exe files created on one computer cannot run on other
computers without first installing the digital certificate which was used
to sign them.
UIA.exe files cannot be started via CreateProcess due to security
restrictions. ShellExecute can be used instead. Run tries
both.
UIA.exe files cannot be modified, as it would invalidate the
file's digital signature.
Because UIA programs run at a different "integrity
level" than other programs, they can only access objects registered by
other
UIA programs. For example, ComObjActive("Word.Application") will fail because Word is not marked for UI Access.
The script's own windows can't be automated by non-UIA
programs/scripts for security reasons.
Running a non-UIA script which uses a mouse hook (even as simple
as #InstallMouseHook) may prevent all mouse
hotkeys from
working when the mouse is pointing at a window owned by a UIA
script, even hotkeys implemented by the UIA script itself. A
workaround is to ensure UIA scripts are loaded last.
For more details, see Enable interaction with administrative programs on the
archive forum.
Scripts
Related topics:
Using the Program: How to
use AutoHotkey, in general.
Concepts and Conventions: General explanation of various concepts utilised by AutoHotkey.
Scripting Language:
Specific details about syntax (how to write scripts).
Table of
Contents
Introduction
The Top of the Script (the Auto-execute Section): This portion executes automatically when the script starts.
Splitting a Long Line into a Series of Shorter Ones: This
can improve a script's readability and maintainability.
Convert a Script to an EXE (ahk2exe): Convert a .ahk script into a .exe file that
can run on any PC.
Passing Command Line Parameters to a Script: The
variables %1%, %2%, etc. contain the incoming parameters.
Script File Codepage: Using
non-ASCII characters safely in scripts.
Debugging a Script: How to find the flaws in a misbehaving script.
Introduction
Each script is a plain text file containing lines to be executed
by the program (AutoHotkey.exe). A script may also contain hotkeys and hotstrings, or even
consist entirely of them. However, in the absence of hotkeys and
hotstrings, a script will perform its commands sequentially from top to bottom
the moment it is launched.
The program loads the script into memory line by line, and each
line may be up to 16,383 characters long. During loading, the script is optimized and
validated. Any syntax errors will be displayed, and they must be
corrected before the script can run.
The Top
of the Script (the Auto-execute Section)
After the script has been loaded, it begins executing at the top
line, continuing until a Return, Exit, hotkey/hotstring label, or the physical end of the script is encountered (whichever comes first). This top portion of
the script is referred to as the auto-execute section.
Note: While the script's first hotkey/hotstring label has the same
effect as return, other
hotkeys and labels do not.
A script that is not persistent and that lacks hotkeys, hotstrings, OnMessage, and GUI will terminate after the auto-execute section has completed.
Otherwise, it will stay running in an idle
state, responding to events such as hotkeys, hotstrings, GUI events, custom menu items, and timers.
Every thread launched
by a hotkey, hotstring, menu item, GUI event, or timer starts
off fresh with the default values for the following attributes as set in the
auto-execute section. If unset, the standard defaults
will apply (as documented on each of the following pages): DetectHiddenWindows, DetectHiddenText,
SetTitleMatchMode, SetBatchLines, SendMode, SetKeyDelay, SetMouseDelay, SetWinDelay, SetControlDelay, SetDefaultMouseSpeed, CoordMode,
SetStoreCapsLockMode, AutoTrim, SetFormat, StringCaseSense, Thread, and Critical.
If the auto-execute section takes a long time to complete (or
never completes), the default values for the above settings will be put into
effect after 100
milliseconds. When the auto-execute section finally completes (if
ever), the defaults are updated again to be those that were in effect at the
end of the auto-
execute section.
Thus, it's usually best to make any desired changes to the defaults at the top
of scripts that contain hotkeys, hotstrings, timers, or custom
menu items. Also note that each thread retains its own
collection of the above settings. Changes made to those settings will not
affect other threads.
Splitting
a Long Line into a Series of Shorter Ones
Long lines can be divided up into a collection of smaller ones to
improve readability and maintainability. This does not reduce the script's
execution speed
because such lines are merged in memory the moment the script
launches.
Method #1: A line that
starts with "and", "or", ||, &&, a comma, or a period is
automatically merged with the line directly above it (in v1.0.46+, the same is
true for all other expression operators except ++ and --). In the following example, the second line is
appended to the first because it begins with a comma:
FileAppend, This is the text to append.`n ; A comment is allowed here.
,
%A_ProgramFiles%\SomeApplication\LogFile.txt ; Comment.
Similarly, the following
lines would get merged into a single line because the last two start with
"and" or "or":
if (Color = "Red" or Color = "Green" or Color = "Blue" ; Comment.
or Color =
"Black" or Color = "Gray" or Color =
"White") ;
Comment.
and ProductIsAvailableInColor(Product,
Color) ; Comment.
The ternary operator is also a good candidate:
ProductIsAvailable
:= (Color = "Red")
? false ;
We don't have any red products, so don't bother calling the function.
:
ProductIsAvailableInColor(Product, Color)
Although the indentation used in the examples above is optional,
it might improve clarity by indicating which lines belong to ones above them.
Also, it is not necessary to include extra spaces
for lines starting with the words "AND" and "OR"; the
program does this automatically. Finally, blank lines or comments
may be added between or at the end of any of the lines in the
above examples.
Method #2: This method
should be used to merge a large number of lines or when the lines are not
suitable for Method #1. Although this method is
especially useful for auto-replace hotstrings, it can also be used with any command or expression. For example:
; EXAMPLE #1:
Var =
(
Line 1 of the
text.
Line 2 of the text. By default, a
linefeed (`n) is present between lines.
)
; EXAMPLE #2:
FileAppend, ;
The comma is required in this case.
(
A line of text.
By default, the hard carriage return (Enter) between the previous
line and this one will be written to the file as a linefeed (`n).
By default, the tab to
the left of this line will also be written to the file (the same is true for
spaces).
By default,
variable references such as %Var% are resolved to the variable's contents.
), C:\My File.txt
In the examples above, a series of lines is bounded at the top and
bottom by a pair of parentheses. This is known as a continuation section. Notice that the
bottom line contains FileAppend's last
parameter after the closing parenthesis. This practice is optional; it is done
in cases like this so that the comma will be
seen as a parameter-delimiter rather than a literal comma.
The default behavior of a continuation section can be overridden
by including one or more of the following options to the right of the section's
opening
parenthesis. If more than one option is present, separate each one
from the previous with a space. For example: ( LTrim Join| %.
Join: Specifies how
lines should be connected together. If this option is omitted, each line except
the last will be followed by a linefeed character (`n). If the
word Join is specified by itself, lines are connected directly to
each other without any characters in between. Otherwise, the word Join should
be followed
immediately by as many as 15 characters. For example, Join`s would insert a space after each line except the last
("`s" indicates a literal space -- it is a
special escape sequence recognized only by Join). Another example
is Join`r`n, which inserts CR+LF
between lines. Similarly, Join| inserts
a pipe
between lines. To have the final line in the section also ended by
a join-string, include a blank line immediately above the section's closing
parenthesis.
Known limitation: If the Join string ends with a colon, it must
not be the last option on the line. For example, (Join: is treated as the label "(Join" and
(LTrim Join: is unsupported, but (Join:
C is okay.
LTrim: Omits spaces and tabs at the beginning of each line. This
is primarily used to allow the continuation section to be indented. Also, this
option may be
turned on for multiple continuation sections by specifying #LTrim on a line by itself. #LTrim is
positional: it affects all continuation sections physically
beneath it. The setting may be turned off via #LTrim
Off.
RTrim0 (RTrim followed by a
zero): Turns off the omission of spaces and tabs from the end of each line.
Comments (or Comment or Com
or C) [v1.0.45.03+]: Allows semicolon comments inside
the continuation section (but not /*..*/). Such
comments (along with any spaces and tabs to their
left) are entirely omitted from the joined result rather than being treated as
literal text. Each comment can appear to the right of a line or on a new line by itself.
% (percent sign): Treats percent signs as literal rather than as
variable references. This avoids the need to escape each percent
sign to make it literal. This
option is not needed in places where percent signs are already
literal, such as auto-replace hotstrings.
, (comma): Treats commas as delimiters rather than as literal
commas. This rarely-used option is necessary only for the commas between
command
parameters because in function calls, the type of comma does not matter. Also, this option transforms
only those commas that actually delimit parameters. In
other words, once the command's final parameter is reached (or
there are no parameters), subsequent commas are treated as literal commas
regardless of this
option.
` (accent): Treats each
backtick character literally rather than as an escape character. This
also prevents commas and percent signs from being explicitly and
individually escaped. In addition, it prevents the translation of
any explicitly specified escape sequences such as `r and `t.
) [v1.1.01+]: If a closing
parenthesis appears in the continuation section's options (except as a
parameter of the Join option), the line is
reinterpreted as an
expression instead of the beginning of a continuation section.
This allows expressions like (x.y)[z]() to work
without the need to escape the opening
parenthesis.
Remarks
Escape sequences such as
`n (linefeed) and `t (tab) are supported inside the continuation section except
when the accent (`) option has been
specified.
When the comment option is absent, semicolon and /*..*/ comments are not supported within
the interior of a continuation section because they are seen as
literal text. However, comments can be included on the bottom and
top lines of the section. For example:
FileAppend, ; Comment.
; Comment.
( LTrim Join ; Comment.
; This is not a comment; it is literal. Include the
word Comments in the line above to
make it a comment.
), C:\File.txt ; Comment.
As a consequence of the
above, semicolons never need to be escaped within a
continuation section.
A continuation section cannot produce a line whose total length is
greater than 16,383 characters (if it tries, the program will alert you the
moment the script
is launched). One way to work around this is to do a series of
concatenations into a variable. For example:
Var =
(
...
)
Var =
%Var%`n ; Add more text to the variable
via another continuation section.
(
...
)
FileAppend,
%Var%, C:\My File.txt
Since a closing parenthesis indicates the end of a continuation
section, to have a line start with literal closing parenthesis, precede it with
an accent/backtick:
`).
A continuation section can be immediately followed by a line containing
the open-parenthesis of another continuation section. This allows the options
mentioned above to be varied during the course of building a
single line.
The piecemeal construction of a continuation section by means of #Include is not supported.
Convert a Script to an EXE (ahk2exe)
A script compiler (courtesy
of fincs) is included with the program.
Once a script is compiled, it becomes a standalone executable;
that is, AutoHotkey.exe is not required in order to run the script. The
compilation process
creates an executable file which contains the following: the
AutoHotkey interpreter, the script, any files it includes, and any files it has incorporated via the
FileInstall command.
Ahk2Exe can be used in the
following ways:
1. GUI Interface: Run the "Convert .ahk to .exe" item in the Start
Menu.
2. Right-click: Within an open Explorer window, you can right-click
any .ahk file and select "Compile Script" (only available if the
script compiler
option was chosen when AutoHotkey was installed). This creates an
EXE file of the same base filename as the script, which appears after a short
time
in the same directory. Note: The EXE file is produced using the
same custom icon, .bin file and use MPRESS setting that were last used by Method #1
above.
3. Command Line: The
compiler can be run from the command line with the following parameters:
Ahk2Exe.exe /in MyScript.ahk [/out MyScript.exe] [/icon
MyIcon.ico] [/bin AutoHotkeySC.bin] [/mpress 0or1]
For example:
Ahk2Exe.exe /in "MyScript.ahk" /icon
"MyIcon.ico"
Usage:
Parameters containing spaces should be enclosed in double quotes.
If the "out" file is omitted, the EXE will have the same
base filename as the script itself.
Notes:
Compiling
does not typically improve the performance of a script.
As of v1.1.01, password protection and the /NoDecompile switch are
not supported.
The commands #NoTrayIcon and
"Menu, Tray, ShowMainWindow"
affect the behavior of compiled scripts.
Custom version info (as seen in Explorer's file-properties dialog)
can be added to your compiled scripts by using a utility such as Resource
Hacker
(freeware) to edit the file "AutoHotkeySC.bin". This
file is contained in the "Compiler" subfolder where AutoHotkey was
installed. Compile_AHK II
can be used to facilitate this process. As of v1.1.01, the
compiled script can be edited instead of AutoHotkeySC.bin.
The method above can also be used to change existing icons or add
new ones to all compiled scripts.
The built-in variable A_IsCompiled contains 1 if the script is
running in compiled form. Otherwise, it is blank.
When parameters are passed to Ahk2Exe, a message indicating the
success or failure of the compiling process is written to stdout. Although the
message will not appear at the command prompt, it can be
"caught" by means such as redirecting output to a file. [v1.0.43+]
Additionally in
the case of a failure, Ahk2Exe has exit codes indicating the kind of error that
occurred. These error codes can be found at
GitHub
(ErrorCodes.md). [v1.1.22.03+]
The compiler's source code and newer versions can be found at GitHub.
Compressing Compiled Scripts
Ahk2Exe optionally uses MPRESS (a freeware program by MATCODE
Software) to compress compiled scripts. If mpress.exe
is present in the "Compiler" subfolder
where AutoHotkey was installed, it is used automatically unless it is disabled
via /mpress 0 or the GUI setting.
Official website (was
offline in March 2016): http://www.matcode.com/mpress.htm
Mirror (downloads and
information): https://autohotkey.com/mpress/
Note: While compressing
the script executable prevents casual inspection of the script's source code
using a plain text editor like Notepad or a PE resource
editor, it does not prevent the source code from being extracted
by tools dedicated to that purpose.
Passing
Command Line Parameters to a Script
Scripts support command
line parameters. The format is:
AutoHotkey.exe [Switches]
[Script Filename] [Script Parameters]
And for compiled scripts, the format is:
CompiledScript.exe [Switches]
[Script Parameters]
Switches: Zero or more of the following:
Switch Meaning Works
compiled?
/f or /forceLaunch
unconditionally, skipping any warning dialogs. This has the same effect as #SingleInstance Off. Yes
/r or /restartIndicate
that the script is being restarted (this is also used by the Reload command, internally). Yes
/ErrorStdOutSend syntax errors
that prevent a script from launching to stderr rather than displaying a dialog.
See #ErrorStdOut for details. This
/iLib
"OutFile"
[v1.0.47+]: AutoHotkey
loads the script but does not run it. For each script file which is
auto-included via the library mechanism, two lines are written to the file
specified by OutFile. These lines are written in the following format, where
LibDir is the full path of the Lib folder and LibFile is the filename of the library:
#Include LibDir\
#IncludeAgain LibDir\LibFile.ahk
If the output file exists,
it is overwritten. OutFile can be * to write the output to stdout.
If the script contains syntax errors, the output file may be
empty. The process exit code can be used to detect this condition; if there
is a syntax error, the exit code is 2. The
/ErrorStdOut switch can be used to suppress or capture the error message.
No
Script Filename: This can be omitted if there are no Script
Parameters. If omitted (such as if you run AutoHotkey directly from the Start
menu), the
program looks for a script file called AutoHotkey.ahk in the following locations, in this order:
The directory which contains the AutoHotkey executable.
The current user's Documents folder.
The filename AutoHotkey.ahk depends
on the name of the executable used to run the script. For example, if you
rename AutoHotkey.exe to MyScript.exe, it will attempt to find MyScript.ahk. If you run AutoHotkeyU32.exe without parameters, it will look
for AutoHotkeyU32.ahk.
Note: In old versions prior to
revision 51, the
program looked for AutoHotkey.ini in the working directory or AutoHotkey.ahk in
My Documents.
[v1.1.17+]: Specify an asterisk (*) for the filename to read the
script text from standard input (stdin). For an example, see ExecScript().
Script Parameters: The string(s) you want to pass into the script,
with each separated from the next by a space. Any parameter that contains
spaces should
be enclosed in quotation marks. A literal quotation mark may be
passed in by preceding it with a backslash (\"). Consequently, any
trailing slash in a quoted parameter
(such as "C:\My Documents\") is treated as a literal quotation mark
(that is, the script would receive the string C:\My Documents"). To remove
such quotes, use StringReplace, 1,
1, ",, All.
[v1.1.27+]: Incoming parameters, if present, are stored as an
array in the built-in variable A_Args, and can be accessed using array syntax. A_Args[1]
contains the first parameter. The following example exits the
script when too few parameters are passed to it:
if
A_Args.Length() < 3
{
MsgBox % "This
script requires at least 3 parameters but it only received "
A_Args.Length() "."
ExitApp
}
If the number of parameters passed into a script varies (perhaps
due to the user dragging and dropping a set of files onto a script), the
following example can be used to extract them one by
one:
for n, param in
A_Args ; For each parameter:
{
MsgBox Parameter number %n% is %param%.
}
If the parameters are file names, the following example can be
used to convert them to their case-corrected long names (as stored in the file
system), including complete/absolute path:
for n, GivenPath
in A_Args ; For each parameter (or file dropped
onto a script):
{
Loop Files, %GivenPath%, FD ;
Include files and directories.
LongPath := A_LoopFileFullPath
MsgBox The case-corrected long path name of
file`n%GivenPath%`nis:`n%LongPath%
}
Known limitation: dragging files onto a .ahk script may fail to
work properly if 8-dot-3 (short) names have been turned off in an NTFS file
system. One
work-around is to compile the script then drag the files onto the resulting EXE.
Legacy: The command line parameters are also stored in the variables %1%,
%2%, and so on, as in versions prior to [v1.1.27].
In addition, %0% contains the number of
parameters passed (0 if none). However, these variables cannot be referenced
directly in an expression because they would be seen as numbers
rather than variables. The following example exits the script when
too few parameters are passed to it:
if 0 < 3 ; The left side of a non-expression if-statement is
always the name of a variable.
{
MsgBox This script
requires at least 3 incoming parameters but it only received %0%.
ExitApp
}
If the number of parameters passed into a script varies (perhaps
due to the user dragging and dropping a set of files onto a script), the
following example can be used to extract them one by
one:
Loop, %0% ; For each parameter:
{
param := %A_Index% ; Fetch the contents of the variable whose
name is contained in A_Index.
MsgBox, 4,, Parameter
number %A_Index% is %param%. Continue?
IfMsgBox, No
break
}
If the parameters are file names, the following example can be
used to convert them to their case-corrected long names (as stored in the file
system), including complete/absolute path:
Loop %0% ; For each parameter (or file dropped onto a
script):
{
GivenPath := %A_Index% ;
Fetch the contents of the variable whose name is contained in A_Index.
Loop %GivenPath%, 1
LongPath = %A_LoopFileLongPath%
MsgBox The case-corrected long path name of
file`n%GivenPath%`nis:`n%LongPath%
}
Script
File Codepage [AHK_L 51+]
The characters a script
file may contain are restricted by the codepage used to load the file.
If the
file begins with a UTF-8 or UTF-16 (LE) byte order mark, the appropriate
codepage is used and the /CPn switch is ignored.
If the /CPn switch is passed on the command-line, codepage n is used. For a
list of valid numeric codepage identifiers, see MSDN.
In all other cases, the system default ANSI codepage is used.
Note that this applies only to script files loaded by AutoHotkey,
not to file I/O within the script itself. FileEncoding controls
the default encoding of files read or written
by the script, while IniRead
and IniWrite
always deal in UTF-16 or ANSI.
As all text is converted (where necessary) to the native string format, characters which are invalid or don't exist in the native
codepage are replaced with a
placeholder: ANSI '?' or Unicode '�'. In Unicode builds, this should only occur if there are encoding
errors in the script file or the codepages used to save and
load the file don't match.
RegWrite may be
used to set the default for scripts launched from Explorer (e.g. by
double-clicking a file):
; Uncomment the appropriate line below or leave them all commented
to
; reset to the default of
the current build. Modify as necessary:
; codepage = 0 ;
System default ANSI codepage
; codepage =
65001 ; UTF-8
; codepage =
1200 ; UTF-16
; codepage =
1252 ; ANSI Latin 1; Western European
(Windows)
if (codepage !=
"")
codepage := " /CP" . codepage
cmd="%A_AhkPath%"%codepage% "`%1" `%*
key=AutoHotkeyScript\Shell\Open\Command
if A_IsAdmin ; Set for all users.
RegWrite, REG_SZ, HKCR, %key%,, %cmd%
else ; Set for current user only.
RegWrite, REG_SZ, HKCU,
Software\Classes\%key%,, %cmd%
This assumes AutoHotkey has already been installed. Results may be
less than ideal if it has not.
Debugging a Script
Commands such as ListVars and Pause can help you debug a script. For example, the following two
lines, when temporarily inserted at carefully chosen
positions, create "break points" in the script:
ListVars
Pause
When the script encounters these two lines, it will display the
current contents of all variables for your inspection. When you're ready to
resume, un-pause the script via the File or Tray menu.
The script will then continue until reaching the next "break point"
(if any).
It is generally best to insert these "break points" at
positions where the active window does not matter to the script, such as
immediately before a WinActivate command.
This allows the script to properly resume operation when you un-pause it.
The following commands are
also useful for debugging: ListLines, KeyHistory, and OutputDebug.
Some common errors, such as typos and missing "global"
declarations, can be detected by enabling warnings.
Interactive Debugging [AHK_L 11+]
Interactive debugging is
possible with a supported DBGp client.
Typically the following actions are possible:
Set and remove breakpoints on lines - pause execution when a breakpoint is
reached.
Step through code line by line - step into, over or out of
functions and subroutines.
Inspect all variables or a specific variable.
View the stack of running subroutines and functions.
Note that this
functionality is disabled for compiled scripts.
To enable interactive
debugging, first launch a supported debugger client then launch the script with
the /Debug command-line switch.
AutoHotkey.exe
/Debug=SERVER:PORT ...
SERVER and PORT may be
omitted. For example, the following
are equivalent:
AutoHotkey /Debug
"myscript.ahk"
AutoHotkey
/Debug=localhost:9000 "myscript.ahk"
[AHK_L 59+]: To attach the
debugger to a script which is already running, send it a message as shown
below:
ScriptPath = ; SET THIS TO THE FULL PATH OF THE SCRIPT
DetectHiddenWindows
On
IfWinExist
%ScriptPath% ahk_class AutoHotkey
; Optional parameters:
; wParam
= the IPv4 address of the debugger client, as a 32-bit integer.
; lParam
= the port which the debugger client is listening on.
PostMessage
DllCall("RegisterWindowMessage", "str",
"AHK_ATTACH_DEBUGGER")
Once the debugger client is connected, it may detach without
terminating the script by sending the "detach" DBGp command.
Script Showcase
See this page for some useful scripts.
Changes & New Features
Changes and new features introduced by the current branch of
AutoHotkey development (a.k.a. AutoHotkey_L) are listed below.
For older changes, see Archived Changes.
1.1.30.00
- August 22, 2018
Fixed SendInput/SendPlay to
restore DownR/remapped modifiers.
Increased limit of hotkeys
per script from 1000 to 32762.
Changed commands which accept On/Off/Toggle to also accept 1/0/-1
(where documented).
Improvements to debugger (DBGp) support:
Added
support for the -d (stack depth) option.
Added (DBGp-only) .<base> pseudo-property to resolve
ambiguity.
Fixed debugger to avoid unsupported re-entry during break state.
Fixed DBGp command parser to support quoted parameters.
1.1.29.01
- June 2, 2018
Fixed WinMove crashing the program in some cases [broken by
v1.1.29.00].
Fixed Gui x:Default if no Gui has been created
[broken by v1.1.29.00].
1.1.29.00 - May 25, 2018
Added Object.Count() and ObjCount(Object).
Added ObjGetBase(Object) and ObjSetBase(Object, Base).
Added ObjRawGet(Object, Key).
Added OnError(Func
[, AddRemove]).
Revised exception handling:
If unhandled, show an error message/call OnError before the stack
unwinds (making exceptions consistent with runtime errors).
Fixed __Delete causing commands to throw even when Try is not used.
Fixed COM clients unable to catch built-in script errors.
Removed the limits on the
number of custom modifiers that can be used with each key.
Changed Send
{Text} to avoid toggling CapsLock or waiting for
Win+L.
Fixed #Warn ClassOverwrite
to not warn for A_Args.
Improved DBGp source command
to properly convert between file codepage and UTF-8, and to reduce code size.
Other code size optimizations and trivial maintenance.
1.1.28.02
- April 7, 2018
Fixed Control
ChooseString and ControlGet FindString ignoring the first two items.
Fixed Control
ChooseString to send WM_COMMAND even if the control's ID is
0.
Fixed WinActivate to restore the active window, as originally
intended for [v1.1.20.00].
1.1.28.01 - March 31, 2018
Fixed Thread treating
omitted parameters as 0.
Fixed FileAppend to stderr
(**).
Fixed break label being able to jump to an unrelated loop.
Reverted hotstring reset
behaviour to pre-v1.1.28.00.
Added Hotstring("Reset") for manually resetting the hotstring
recognizer.
1.1.28.00 - February 11, 2018
Changes:
Changed
__Delete to catch and report exceptions when called during object cleanup. It
previously had the (erroneous) effect of
"postponing" the exception until the next function call
or the end of the try-block/thread.
Changed hotstring recognizer to reset when focus changes instead
of just when the active window changes.
Changed WinMenuSelectItem to treat menu 0& as the window's system menu.
New features:
Added
support for all built-in variables in the path passed to #Include.
Added A_TimeIdleKeyboard and A_TimeIdleMouse.
Added A_ListLines.
Added A_ComSpec (alias
of ComSpec).
Added A_LoopFilePath (alias
of A_LoopFileFullPath, which is a misnomer).
Added hotstring X option to
execute a same-line action instead of auto-replace.
Added Hotstring().
Added function hotstrings.
Added MaxParts parameter to StrSplit.
Improved #MenuMaskKey to allow specifying VK and SC, or vk00sc000.
Bug fixes:
Fixed
#MenuMaskKey treating some valid keys (such as Del) as invalid.
Optimised detection of AltGr on Unicode builds. This fixes a delay
which occurred at startup (since v1.1.27.00) or the first time
Send is called for each target keyboard layout (prior to
v1.1.27.00).
Fixed misleading vicinity lines for x up::y remap error.
Fixed Menu
Tray, Icon, HICON:%hicon%, which now uses hicon
without resizing it.
1.1.27.07
- January 21, 2018
Fixed default size of Gui
with +Parent to not be restricted by parent [broken by v1.1.27.05].
Fixed controls not redrawing if a separate Tab control is
shown/hidden immediately after the control was invalidated (such as when
showing/hiding multiple controls at once).
1.1.27.06
- January 16, 2018
Fixed hotstrings/Input causing stuck dead keys (broken by
v1.1.27.05).
1.1.27.05 - January 16, 2018
Fixed visible Input end keys causing any pending dead key to
double up.
Fixed hotstrings/Input affecting how Tab/Esc act in a dead key sequence.
Fixed A_IconFile returning an incorrect path if a DLL was used.
Fixed Gui with +Parent to
center within the parent GUI vs. the screen.
Fixed Input/hotstring
detection of dead key sequences in Universal Windows Platform (UWP) apps.
Fixed <
& v and > & v being seen as duplicates, and similar cases. This affects custom
combinations where the prefix key is also a
modifier symbol. This also fixes hotkeys which consist only of
modifier symbols and a single trailing space, such as + ::, to be treated as
errors rather than ignoring the space (hotkeys do not
permit trailing space).
1.1.27.04
- January 10, 2018
Fixed #Warn ClassOverwrite giving erroneous warnings.
1.1.27.03 - January 6, 2018
Improved Menu x, NoStandard and Menu x, DeleteAll to work
without attempting to destroy the underlying Win32 menu. This
allows them to work when x is a menu bar or sub-menu of one.
Reworked the handling of vkXXscYYY:
Fixed
GetKeyVK and GetKeyName treating vkXXscYYY as vk00scYYY.
Send is now more strict with {vk...} and invalid suffixes,
consistent with similar changes made by [v1.1.27.00] (but sc is still
supported).
Reduced code size.
Fixed mishandling of numeric keys outside the 32-bit range (but
inside the 64-bit range) in some corner cases on 64-bit builds. This only
affects classes which use such numbers as names (not
recommended for multiple reasons) and array access via IDispatch with such
numbers as keys/member names.
1.1.27.02
- January 1, 2018
Fixed loading of bmp files
as icons at original size.
Fixed compound assignments such as Test.Prop[1] += 1 (broken by v1.1.27.01).
1.1.27.01 - December 31, 2017
Fixed program crashes
caused by ++X or --X in scripts which lack #NoEnv (broken by v1.1.27.00).
Fixed #Warn ClassOverwrite
giving an erroneous warning for ++MyClass.X.
Fixed remapping to allow
custom combinations such as a
& b::c.
Fixed Send/hotstrings/Input to adapt to the keyboard layout of the
focused control instead of just the active window. In particular, this
affects UWP apps such as Microsoft Edge.
Fixed hook hotkeys to suppress the Start menu activation which
occurs when an isolated Ctrl/Shift up is received. Ctrl up may be
generated by the system when switching from a keyboard layout with
AltGr to one without (such as from UK to US), if Ctrl is not held
down at the time. This fixes hotkeys such as $#z::WinActivate
x when the change in focus causes those conditions.
Fixed Input not collecting
characters when both Shift keys are down.
Fixed Input to use "sc" and "vk" for end keys
in ErrorLevel rather than "Sc" and "Vk" (caused by
v1.1.20).
Fixed GetKeyName/VK/SC("vkXXscYYY") where YYY begins with A-F (broken by v1.1.26).
1.1.27.00
- December 25, 2017
Changes:
Replaced AU3_Spy.exe with
WindowSpy.ahk.
AU3_Spy.exe
is still launched if WindowSpy.ahk is not found.
It now follows the focused control by default, and has a checkbox
for both window and control to follow the mouse.
It no longer takes over a global hotkey (Win+A). Instead, hold
Ctrl or Shift to suspend updates (release them after focusing
Window Spy).
It is now possible to Alt-Tab to Window Spy on Windows 10 without
the contents of the GUI changing.
Changed a-z to mean vk41-vk5A when absent from the keyboard layout, except
with Raw mode or when sending single unmodified
characters. This allows hotkeys and sent keyboard shortcuts to
work more intuitively on certain non-English keyboard layouts.
Changed Send on ANSI versions to use SendInput() in place of Alt+nnnnn for special characters.
Changed the rules for masking Alt/Win after pressing a hook hotkey:
Explicitly sent Alt/Win up may be masked. This fixes remappings
such as AppsKey::RWin, but hotkeys which are intended to
activate the Start Menu may require new workarounds.
If Alt/Win is logically but not physically down, only hotkeys
which require Alt/Win (such as #a::, not *a::) cause masking. This
is to allow a remapping or wildcard hotkey to send the key-up
without it being masked.
Unsuppressed hotkeys such as ~#a:: no longer cause masking, because the unsuppressed keydown/keyup
is sufficient to prevent a
menu. However, mouse hotkeys like ~*MButton:: no longer suppress the Start Menu if combined with the Win key. It can be
suppressed manually with Send {Blind}{vk07} or similar.
The keyboard hook now tracks events in relation to Alt/Win, so
that the mask key does not need to be sent if Alt/Win was already
masked by some other event (physical or sent).
The hotkeys ~LWin:: and ~RWin:: no longer suppress the
Start Menu. See #MenuMaskKey for details and a workaround.
Added proper validation for
vk or sc key names, so names such as "sc01notvalid" are no longer
recognized as keys.
Scripts containing hotkeys of the form VKnnSCnnn:: will need to be corrected by removing SCnnn, which was previously
ignored.
Help file: Replaced the standard HTML Help Viewer sidebar with the
new HTML5 sidebar developed by Ragnar-F.
New features:
Added Min/Max built-in functions. [PR #84 from Ragnar-F]
Added A_Args as an
alternative to the numbered variables.
Added force-local mode for
functions.
Added #Warn ClassOverwrite.
Added {Text} mode for Send
and T option for
hotstrings. These are like the Raw mode, but more reliable.
Added {key DownR} and changed remapping to use it, to fix issues with AppsKey::RWin and similar.
Bug fixes:
Fixed
icon-loading to not default to ID 0 when the index is invalid.
Fixed VK↔SC mapping of PrintScreen. SC→VK was already
correct on Vista and later.
Fixed Hotkey control returning scXXX instead of names in some
cases.
Fixed ListVars crashing if a ByRef parameter refers to a variable
containing an object. [PR #86 from HotKeyIt]
Fixed some (very unlikely) memory leaks.
Fixed menu handles not being freed if only the standard items are
used.
Fixed bold font not being applied to default menu item if it has a
submenu and a Win32 menu handle.
Fixed Send to use the correct modifier state with Unicode chars.
Fixed ControlSend
{u n}, where u is Unicode, to send n times, not just 1.
Fixed inconsistent behavior of AltGr between OS versions.
Specifically, RAlt:: once again causes the system to "release" LCtrl on
Windows 10, as it did prior to v1.1.26.01 (but unlike those old
versions, it prevents the RAlt-up from reaching the active window).
This change should not affect layouts without AltGr.
Fixed Menu
Tray, Icon, SB_SetIcon and LoadPicture with non-zero Icon
option to allow bitmaps (but convert if needed).
Fixed menu items to not disappear when a cursor is set as a menu
item's icon.
Improved launching of Window Spy and the help file:
If AutoHotkey is installed but the current executable is in a
different directory (i.e. portable), the installed file is no longer
preferred as it may be the wrong version. It may still be used as
a fallback.
On failure to launch the file, show the error message inside the
dialog, not in its titlebar.
Fixed one-line hotkeys with expressions beginning in sc or vk.
Fixed >/< hotkey
modifiers incorrectly allowing both keys to be pressed. For example, <^A could erroneously be triggered by
LCtrl+RCtrl+A, thereby preventing the <>^A hotkey from working.
Fixed auto-replace hotstrings inserting the literal text
"{Raw}" in some cases (specifically, when the replacement contains {Raw}
and the O, R and * options were not used).
Fixed some hotkeys not using the hook when eclipsed by a wildcard
hotkey, depending on the order of definition.
Fixed key-down hotkeys to revert to "reg" if they were
only "k-hook" because of a corresponding key-up hotkey which has
since
been disabled. (Prior to v1.1.07.03 this already happened, but the
key-down hotkey was never set to "k-hook" in the first place if
defined after the key-up.)
Fixed hook hotkeys to ignore modifier changes made by Send
!^+#{key} or when sending Unicode characters. This
restores Send
to how it was prior to v1.1.06 when at SendLevel 0, but keeps the
v1.1.06+ behavior at SendLevel >= 1, allowing Send to trigger
the right hotkeys.
Improved the odds that Send from a "reg" hotkey such as ^m::Send x will
restore the modifier state if Send is being called for the
very first time. This makes it less likely to produce a different
(and unexpected) result the first time it is held down, such as xmmm
instead of xxxx.
1.1.26.01
- July 16, 2017
Fixed RegDelete (with no args) failing when A_LoopRegSubKey is
blank, such as when enumerating keys directly under the root key.
Fixed RAlt/LAlt:: sometimes failing to prevent menu activation after the user
alt-tabs away from a window and reactivates it.
Fixed SC → VK translation for multimedia keys, PrintScreen,
CtrlBreak, Pause, LWin and RWin, with the exception that multimedia
keys, PrintScreen and CtrlBreak are still translated incorrectly
on Windows 2000 and XP.
Fixed VK → SC
translation for multimedia keys, CtrlBreak and Pause.
Fixed 'Wait commands such as RunWait to log extra lines for
ListLines only when necessary to show that it is still waiting; that is, after
resuming from an interruption which logged other
lines.
1.1.26.00
- June 10, 2017
Changed the format ListVars uses to display variables containing
objects. The object's class name is now shown.
Added "class" and "clsid" modes to
ComObjType().
Revised class names shown
by the debugger and significantly reduced code size in the process.
Revised FileSetAttrib, FileSetTime and FileDelete to reduce code
size. There should not be any changes in behaviour.
Made other minor optimizations to code size.
Fixed GetKeySC() with the
key names Esc, Escape, ScrollLock and PrintScreen.
Fixed hotstring word
detection of words containing nonspacing marks, such as Arabic diacritics.
1.1.25.02
- May 13, 2017
Fixed GUI option strings being permanently truncated if an error
is raised.
Fixed properties and class sub-variables to allow non-ASCII
characters.
Fixed new operator to allow __New to
throw or exit.
1.1.25.01
- March 5, 2017
Fixed Send to allow other scripts to act on modifier state changes
which immediately precede a special character, such as the Shift
release in Send Mört.
1.1.25.00
- March 4, 2017
Added Hotkey, If, % FunctionObject.
Fixed website address in Help menu.
1.1.24.05 - February 3, 2017
Fixed WinSet AlwaysOnTop/Trans/TransColor to work on windows with
0 ExStyle.
1.1.24.04 - December 17, 2016
Fixed File.ReadNum() repeating old data if a prior
File.Read() had stopped reading at the
end of the buffer.
Improved buffer utilisation when File.Read() reaches the end of the buffered data.
Fixed GuiControl +Password to use the default bullet character on XP and later.
Fixed GuiControl +/-Password to redraw the control
immediately.
1.1.24.03
- November 19, 2016
Fixed COM exception
messages to not end in `r.
Fixed {U+x} to
support supplementary characters (x > 0xFFFF).
Fixed class properties which lack get{} to return an empty value
instead of the internal Property object when the class has a base which
does not define a value for the property. Properties defined in
baseless classes already behaved correctly.
Fixed the background color
of controls on a Tab3 control when the system has visual styles disabled (i.e.
Windows Classic).
Fixed handling of thread-exit in functions which are called
directly by an event (such as OnExit functions). This bug had no known effect
except in the v2-alpha branch.
Fixed the debugger to detect disconnection immediately (i.e. when
a client terminates without calling stop/detach).
Fixed the debugger to treat property_get
-m 0 as "unlimited", as per the DBGp spec.
Fixed the debugger to
expect base64 for property_set -t integer/float, as per the DBGp spec.
1.1.24.02
- October 13, 2016
Added a Run with UI Access option
to the installer.
Added documentation for Tab3 autosizing.
Fixed several Tab3 bugs:
Autosizing was not being triggered by the first call to Gui Show if the AutoSize or w and h options were used.
If a Tab3 control is empty when autosizing occurs, it now retains
the default size instead of becoming unusable.
Autosizing now occurs immediately before creating another tab
control, as though Gui Tab was
called.
Autosizing failed if the tab control had negative screen coords.
Hiding a Tab3 control with GuiControl now also hides its
dialog/background.
Fixed OnMessage to pass
lParam as unsigned on 32-bit.
Fixed Gui Name : to allow
spaces before the colon.
Fixed identifying a Gui or
GuiControl by HWND with a negative value.
Fixed ComObject to suppress any errors raised by disconnection of events after the script has released the object.
Fixed Gui Show causing the window to shrink if it had a multi-line
menu bar.
Fixed LV_InsertCol(n, width) not causing ListView scrollbar to update on some OS versions.
Optimized code size of
FileRecycleEmpty.
1.1.24.01
- August 2, 2016
Changed Hotkey, If, Expression to raise
an error if the unused third parameter is not blank.
Fixed &&, || and ternary to release any object used as the
condition, as in if
(a.subObject && b).
Fixed Gui/GuiControl failing to "check" radio buttons
within a Tab3 control.
Fixed FileCreateShortcut to
allow relative paths for the LinkFile parameter on Windows 10.
Fixed themed Tab3 control
to not override the custom text color of its controls.
Fixed debugger mishandling
continuation commands in some specific cases.
1.1.24.00
- May 22, 2016
Breaking changes:
Passing SetTimer's Label parameter an empty variable or an expression which results in an
empty value is now considered an error. The parameter must be either given a non-empty value or completely omitted.
Run-once timers are
automatically deleted after running if they are associated with an object
created by the script. This allows the object to be freed if the script is no longer referencing it, but
it also means the timer's Period and Priority are not retained.
SetTimer, Hotkey, GuiControl and Menu now check the minimum
parameter count of functions given by reference (not just by name, as
in previous versions). If the function requires too
many parameters, an error is raised or ErrorLevel is set (as appropriate).
Backward-compatible
changes:
If SetTimer's Label parameter is omitted and A_ThisLabel is empty, the current timer (if any) is used.
New features:
Added Tab3 control type, solving
a number of issues with Tab controls.
Bug-fixes:
Fixed GuiControl to update
controls when adding/deleting tabs. Specifically:
Selecting a new tab with || now
works correctly.
Deleting all tabs now hides the controls of the former tab.
Fixed +Disabled/+Hidden losing effect on controls in a tab.
Fixed disabled tab controls to ignore Ctrl+Tab.
Fixed Gui Tab without parameters to
start a new radio group if applicable. Gui Tab with parameters already
had this effect.
1.1.23.07 - May 20, 2016
Fixed Menu x, Insert, y, z, % object to use the object, not
ignore it.
Fixed Menu
x, Add, :item text, % object to use the object, not look for a submenu.
1.1.23.06 - May 15, 2016
Fixed break
label crashing the program if nested directly inside its target loop.
1.1.23.05 - March 27, 2016
Fixed InputBox, MsgBox, FileSelectFile and FileSelectFolder
sending an unwanted Alt-up if Alt is down. This was due to an error with
the Ctrl/Shift workaround added in v1.1.22.01.
Improved the Ctrl/Shift workaround to avoid unnecessarily
"masking" the Win key if Ctrl, Shift or Alt is also down.
1.1.23.04 - March 26, 2016
Fixed LV_Modify to support omitting Options, as in LV_Modify(r,, col1).
1.1.23.03 - March 12, 2016
Fixed __Delete meta-functions erroneously suppressing or
prematurely re-throwing exceptions, when they are called during exception
propagation.
Fixed load-time detection of function calls where a required
parameter is blank, as in fn(x,,y).
1.1.23.02 - March 12, 2016
Fixed RegDelete deleting the entire key instead of the default
value.
Code maintenance; minor code size improvement.
1.1.23.01
- January 24, 2016
Fixed a theoretical issue with loading scripts from weird/very
long paths.
Ahk2Exe: Fixed Unicode in compiled scripts (broken by v1.1.23.00
release).
1.1.23.00 - January 16, 2016
Added Menu Insert sub-command.
Added MenuGetHandle().
Added MenuGetName().
Added menu item options:
Radio, Right, Break and BarBreak.
Improved the Menu command
to allow identifying items by position: 1&
Added LoadPicture().
Added hicon/hbitmap: syntax for passing handles to commands which normally load an image from
file.
Added built-in variables: A_CoordModeToolTip/Pixel/Mouse/Caret/Menu,
A_DefaultGui, A_DefaultListView, A_DefaultTreeView, A_KeyDelayPlay, A_KeyDuration/Play, A_MouseDelayPlay,
A_SendLevel, A_SendMode and A_StoreCapsLockMode.
Added Ix Hotkey option to set the
hotkey variant's input level to x.
Improved Picture control to support BackgroundTrans with icons.
Improved Picture control to reduce flicker when loading large
images.
Small optimizations to the
menu code and built-in var lookups.
Fixed conversion of menu
items to/from separators.
Fixed A_ThisMenuItemPos to
support duplicate item names.
Fixed sub-menus sometimes
not being recreated after a menu is deleted.
Fixed AutoHotkeyXXX.exe to launch AutoHotkey.chm, not
AutoHotkeyXXX.chm.
1.1.22.09 - November 11, 2015
Fixed some issues with
SetTimer Delete.
KeyHistory's
timer count erroneously included deleted timers.
Calling KeyHistory within a thread started by a timer crashed the
script if the timer had been deleted but not turned off.
Deleting the most recently created timer prevented subsequently
created timers from working unless ALL timers were deleted.
1.1.22.08
- November 11, 2015
Fixed For-loop to pass
control correctly when _NewEnum/Next throws an exception.
Fixed Finally to suspend the pending exception until its body has
been evaluated, not just until the first built-in function call.
Fixed load-time detection of invalid jumps from Finally blocks
(broken by v1.1.20).
1.1.22.07
- September 27, 2015
Fixed Gui control w-1 and h-1 options failing when DPI is 150+% and the Gui has not applied -DPIScale.
Fixed ~key up hotkeys
to not perform an automatic Send
{key down}. This
was occurring only if the hotkey was turned on after the key
was pressed down.
1.1.22.06
- September 13, 2015
Fixed Input and hotstrings
to catch Unicode/non-key character events.
Fixed auto-sizing of Edit
controls to include the last line if blank.
Fixed handling of
out-of-memory in ComObj functions.
Fixed ComObjArray to ignore excess parameters rather than crashing
(only applies to dynamic calls).
Fixed GuiControl to append--not prepend--tabs, as documented.
Fixed XP64 support.
1.1.22.05
- September 10, 2015
Fixed icons which have
non-numeric IDs loading with sub-optimal quality.
Fixed Gui Destroy not releasing function objects which were set by
the +g option.
Fixed Gui Show to avoid attempting to force-activate a child GUI.
Fixed failure to set
Caps/Num/ScrollLock state while the key is down.
Fixed Gui Color causing
incorrect text color (usually black).
Changed Gui Show to improve
the odds of GuiSize executing immediately.
For developers:
Modified
project config to support more VC++ versions.
Fixed various build warnings on VC++ 2015.
64-bit binaries are now built with VC++ 2015. 32-bit binaries
still use VC++ 2010.
1.1.22.04
- August 19, 2015
Fixed ObjRawSet() to return
nothing.
Added Windows 10 supportedOS tag to the exe manifest (avoids some
issues with the Program Compatibility Assistant and similar).
Added detection of syntax errors after ")" in a function
declaration.
1.1.22.03
- July 12, 2015
Fixed A_EndChar returning a truncated value for Unicode end chars.
Small implementation changes:
Changed
A_Language to use GetSystemDefaultUILanguage().
Refactored Window Spy/help file launching from tray menu to
improve code re-use.
Optimized Gui/Menu/Hotkey/Hotstring/OnClipboard message handling
(minor).
1.1.22.02
- May 27, 2015
Fixed TreeView to not raise * events
for unknown notifications.
Fixed crashing/bad
behaviour when a timer deletes itself.
Fixed RWin-up being masked in some
rare cases where LWin-up wouldn't have been.
1.1.22.01 - May 24, 2015
Fixed Text/Edit/Button
control sizing to compensate for character overhang.
Fixed registry commands to
allow : in the SubKey when combined with RootKey.
Fixed hotkey prioritization
to take modifiers into consideration.
Refactored
else/try/catch/finally handling to support hotkey::try
cmd.
Added a workaround for the script's dialogs acting as though Ctrl
or Shift is pressed after they are blocked by the keyboard hook.
1.1.22.00 - May 1, 2015
Added SetErrorMode(SEM_FAILCRITICALERRORS) on program startup to
suppress system-level error messages such as "There is no
disk in the drive". Calling Drive or DriveGet no
longer affects the process' error mode.
Changed MonthCal controls
to have tab-stop by default on Vista or later.
Improved ComObjConnect to
use IProvideClassInfo when available.
Fixed some issues with method/property definitions following an
end brace on the same line.
Fixed Text/Link control auto-sizing to compensate for the +Border
(WS_BORDER) style.
Fixed Break
N when Loop is used directly below If/Else/Try/Catch.
1.1.21.03
- April 12, 2015
Fixed detection of naming conflicts between properties and
methods.
1.1.21.02 - April 4, 2015
Fixed OnMessage(msg,
fnobj, 0) to do nothing if fnobj wasn't previously
registered.
1.1.21.01 - April 3, 2015
Fixed StrReplace() to allow ReplaceText to be omitted.
Fixed class variables to allow non-ASCII names.
1.1.21.00 - March 28, 2015
Added Loop, Reg, RootKey[\Key, Mode].
Added Loop, Files, FilePattern [, Mode].
Changed InputVar parameters to allow % expression (except with If commands).
Revised Object methods:
Added Object.InsertAt(), Object.Push() and ObjRawSet().
Added Object.Delete(), Object.RemoveAt() and Object.Pop().
Added Object.Length().
Added Ord() and
updated Chr() to support supplementary chars (>0xFFFF).
Added StrReplace().
Removed the obsolete and undocumented 5-parameter mode of RegRead,
which was exclusively for AutoIt v2 compatibility (the extra
parameter was unused).
Changed RegRead, RegWrite and RegDelete so that the RootKey and SubKey parameters can optionally be
combined.
1.1.20.03 - March 21, 2015
Fixed MouseGetPos (OutputVarControl), GuiContextMenu and
GuiDropFiles (A_GuiControl) to not ignore disabled controls [broken by
v1.1.20.00].
1.1.20.02
- March 11, 2015
Fixed add-first mode of
OnMessage.
Fixed A_OSVersion for
unrecognized OSes on x64 builds.
Fixed ExitApp to unpause the script before releasing objects in
case a __delete meta-function is called.
Trivial optimizations and code maintenance.
1.1.20.01
- March 10, 2015
Reverted the changes made
in v1.1.20.00 to saving and restoring of ErrorLevel on thread interrupt, due to
unintended consequences.
ErrorLevel is not reset or cleared when a new thread starts.
Instead, it retains the value it had in the interrupted thread, as in
v1.1.19 and older.
If ErrorLevel contains an object and the thread is interrupted,
the object is replaced with an empty string when the thread resumes,
as in v1.1.19 and older.
If ErrorLevel contains a string longer than 127 characters, it is
truncated when the thread resumes, as in v1.1.19 and older.
Re-fixed timers sometimes causing ErrorLevel to be formatted as
hex.
Fixed class methods to retain a counted reference to the class.
1.1.20.00 - March 8, 2015
New features:
Enhanced Hotkey, Menu, SetTimer, Gui events and Gui control events
to accept a function instead of a label, if no
label is found.
Enhanced Hotkey, Menu, SetTimer and Gui control events to accept a function object. Added a Delete sub-command for SetTimer to
allow the object to be released.
Enhanced OnMessage() to allow
any number of functions or function objects to monitor a single message.
Added OnExit() and OnClipboardChange(), which accept a function name or object.
Added capability to point hotkey labels at a function definition.
Added U/L/T modifiers to perform case conversion with Format().
Added the E option to the
Input command, for handling end keys by character instead of keycode.
Added ** (stderr) support
to FileAppend.
Added ObjBindMethod(obj,
method, args*) and Func.Bind(args*).
Changes:
Changed the default
behavior when the main script file is not found:
If no
script was specified and the default script files are not found, show the new Welcome page in the help file.
If a script was specified or the help file is missing (or is named
differently to the executable), just show an error message.
Changed WinActivate to
restore the window if already active but minimized.
Changed WinActivate to look for a visible window to activate if
DetectHiddenWindows is off and the active window is hidden, instead
of doing nothing.
Changed the method used by
A_CaretX/A_CaretY to retrieve the caret position.
Returns
blank in more cases where the real caret position can't be determined, instead
of returning the top-left of the active
window.
Less likely to cause side-effects.
Works in console windows.
Changed A_OSVersion to use RtlGetVersion(), so that
it can detect Windows 10 and hopefully future versions.
Changed A_OSVersion to return a version number of the form
"major.minor.build" if it doesn't have a name for the OS.
Changed objects to support x[,y], x.y[,z] and x[](y).
User-defined objects can utilize this by specifying default values
for parameters of properties and meta-functions. For __Call, the
first parameter is omitted, as in x.__Call(,y).
COM objects invoke DISPID_VALUE if the member name is omitted. For
example, x[] retrieves x's default property and fn[]()
can be used to call JScript functions.
Several under-the-hood
changes to fix bugs, reduce code size or improve performance, including:
Changes to preparsing of #if and static var initializers.
Changes to preparsing of { blocks }.
Bug-fixes:
Fixed VK to keyname
conversions for keys 'A' to 'Z' to respect layout.
Applies to: GetKeyName, Hotkey control, A_PriorKey, KeyHistory and
Input EndKey ErrorLevel (except where Shift key is
required).
All other keys, including those that produce non-ASCII letters,
were already translated according to AutoHotkey's current
keyboard layout.
Fixed FileAppend to *
(stdout) to respect the encoding parameter instead of always outputting ANSI
text.
Fixed auto-sizing of GUIs
with only one scrollbar.
Fixed Exception(m, n) crashing when n is too far out of bounds.
Fixed GuiContextMenu to set
A_GuiEvent correctly on x64.
Fixed FileGetSize sometimes
giving an indeterminate result if the file doesn't exist or can't be opened.
Fixed thread interrupts to save and restore ErrorLevel more fully
[reverted in v1.1.20.01 due to unintended consequences].
Fixed ControlClick Pos mode to ignore disabled controls.
Fixed odd behaviour when
Gui +MaxSize is smaller than +MinSize.
Fixed GuiControl/Get
requiring a Gui name when given a control HWND.
Fixed meta-functions
interfering with the line number reported by Exception().
1.1.19.03
- February 11, 2015
Improved remapping to allow scXXX::Y when the current keyboard
layout does not map scXXX to a VK code. However, Y must
still exist on the current keyboard layout.
Fixed break n to work
correctly when until is present, instead of terminating the thread.
Fixed ControlGetFocus
disrupting the user's ability to double-click (thanks HotKeyIt).
Fixed ListView to not call the control's g-label for unsupported
(and previously unknown) notifications such as
LVN_GETEMPTYMARKUP.
Fixed #Include *i <X> to exit the program as intended if X has a syntax error.
Fixed for
var in expression sometimes crashing the program when expression calls a script function.
1.1.19.02 - January 25, 2015
Removed the 16-color icons which were used on Win9x/Win2k.
Removed the separate tray icon resources.
Improved selection of icon
size when loading icons from DLL/EXE files.
In short, prefer to downscale rather than upscale. This is
especially helpful on systems with 125% or 150% DPI, where the system
icon sizes are 20/40 or 24/48 instead of 16/32. If all of these
sizes are present in the icon resource, this change makes no difference.
Fixed some issues with
hotkey validation at load time.
Hotkeys
which are never valid, like foo::, are now always treated as errors instead of
giving a misleading warning about keyboard
layout.
Hotkeys like ^!ä:: which are inactive because of the current
keyboard layout are now allowed to have a same-line action, and the
label is registered correctly (e.g. as "^!ä" and not as
"^!ä:"). If the /iLib command line switch is used, the warning is
suppressed.
Remappings which are inactive because of the current keyboard
layout now show two warnings instead of an unrecoverable error.
If a Wheel hotkey is used as a prefix key, there is only one error
message instead of two, and it respects /ErrorStdOut.
Fixed /iLib switch to write the file even if there's a syntax
error.
Fixed return/break/continue/goto in try..finally.
1.1.19.01
- January 5, 2015
Fixed Hotkey command crashing the program when trying to create
new variants of existing hotkeys (broken by v1.1.19.00).
Made some minor optimizations to the Hotkey command and
A_TimeIdle, relating to removal of Win9x support.
1.1.19.00 - January 4, 2015
Added a name for Func.Call(). Func.() still works but is deprecated.
Fixed some issues with X.Y and X.Y(Z) in VBScript/JScript/C#:
If X.__Call contained a function name, it was being returned instead of
called.
When X.Y(Z) returned a value, Z was
ignored. Now it acts like X.Y[Z] when X.Y
is not a function.
Fixed the Hotkey command
ignoring the ~ (pass-through) prefix if Label
was omitted.
Fixed the Hotkey command ignoring the $ (use-hook) prefix if the
hotkey variant was already created without $.
Fixed %Fn%() syntax to work with JavaScript Function objects.
Fixed EXE manifest to
disable UAC installer detection heuristics (broken by v1.1.17).
Improved the way threads
are represented on the debugger's call stack.
The type of thread is shown instead of the label name, which is
still available in the next stack entry. For hotkeys, the hotkey is
shown instead.
The line number of the sub or function that the thread called is
shown instead of the line the script was at before starting the
thread.
1.1.18.00
- December 30, 2014
Improved IDispatch
implementation for AutoHotkey objects:
X.Y in VBScript and C# now
returns X.Y if it is NOT a Func object; previously, it attempted to call X.Y()
regardless of type.
X(Y) in VBScript, JScript and C# now returns X[Y] unless X is a Func
object, in which case it is called as before.
X[Y] in C# now returns X[Y] if X is NOT a Func object; previously, it
attempted to call X[Y]() regardless of type.
X.Y() in C# now returns X.Y if it is NOT a Func
object, due to ambiguity in the C# dispatch implementation.
Unhandled exceptions are now converted to IDispatch exceptions.
Added support for creating new properties in JavaScript/IE DOM
objects.
Fixed FileAppend,
%VarContainingClipboardAll%, File causing crashes.
1.1.17.01 - December 28, 2014
Fixed COM event handlers not receiving the final object parameter.
1.1.17.00 - December 27, 2014
New features:
Added Format().
FileOpen() can now
be used to read from stdin or write to stdout or stderr by passing "*" or "**" as the
filename. AutoHotkey.exe * can
be used to execute script text piped from another
process instead of read from file. For an example, see ExecScript().
Added support for passing
AutoHotkey objects to COM APIs as IDispatch.
Added support for VT_BYREF
in ComObject wrappers. Use obj[] to
access the referenced value.
Bug-fixes:
Fixed blue-screening on XP
SP2.
Fixed owned ComObjArrays to be returned by value, not by pointer.
That is, a copy of the array is returned instead of a pointer to an
array which is about to be deleted.
Changed the URL in the sample script which is created when you
first run AutoHotkey.
Fixed sc15D to map to vk5D/AppsKey (Send, GetKeyName,
etc.).
Fixed Edit controls to not
treat AltGr+A as Ctrl+A.
Fixed static class vars to not act as a target for labels which
immediately precede the class.
1.1.16.05 - September 28, 2014
Fixed x.y/[]/{} sometimes falsely being flagged as variadic.
1.1.16.04 - September 16, 2014
Fixed a crash which
occurred when overwriting a non-writable property.
Fixed a crash which occurred when a RegExMatch object is created
with uncaptured subpatterns during a regex callout.
1.1.16.03 - September 11, 2014
Fixed some bad behaviour in Abs() and Mod() caused by a broken
bug-fix in v1.1.16.01.
1.1.16.02 - September 11, 2014
Fixed parser to allow #include inside a class (broken by a6ea27f).
Fixed Clipboard returning binary CF_HDROP data in some instances.
Improved accuracy of FileGetSize on files which are still open.
Improved for-loop compatibility with COM objects.
1.1.16.01
- September 10, 2014
Added syntax for defining dynamic properties in
classes.
Added x+m and y+m options for Gui control positioning.
Added the #InputLevel of
each hotkey to ListHotkeys (when non-zero).
Optimized RegExMatch with the O (object) option; capturing part of
a long string is much faster than before in some cases.
Fixed objects to check for new methods after __Call completes
(consistent with __Set and __Get).
Fixed some undefined
behaviour occurring after VarSetCapacity fails.
Fixed FileRead to correctly
report an error with files over 4GB, instead of truncating even when it wasn't
requested.
Fixed FileRead *c to
null-terminate correctly when byte length is odd.
Fixed some ClipboardAll
issues and changed behaviour:
#ClipboardTimeout is
ignored for GetClipboardData(), since it never actually worked and it caused
problems. This fixes timeouts
and lost data when a file is on the clipboard (any file on Windows
8, or any file in a zip file or similar).
Zero-length clipboard items are allocated 1 byte upon restoring to
the clipboard, since setting a zero-length item seems to always
fail.
The presence of MSDEVColumnSelect/MSDEVLineSelect is now preserved
when set by Scintilla, though any data set by VS is
discarded.
When writing ClipboardAll directly to file, it now prefers Unicode
(other usages of ClipboardAll have had this behaviour since
v1.1.08).
ClipboardAll and FileRead *c on Unicode builds now round length up
when odd. This increases the reported StrLen by 1,
potentially avoiding truncation of the last byte.
Fixed A_EventInfo for TreeView items with negative screen coords.
Fixed a possible ListView/TreeView message filtering issue.
Fixed
A_LineFile/A_LineNumber in #If expressions.
Fixed #If to add itself to
ListLines (though as "If").
Fixed Abs(["-"]*) and similar crashing the program.
Fixed }
funcdef(){ globally and
}} ending a method/property/class.
1.1.15.04 - August 12, 2014
Fixed a performance issue
with &var_containing_long_string_of_digits.
Fixed built-in variables
corrupting memory when an object is assigned.
Fixed parser to disallow continue where appropriate even if the current function
is defined inside a Loop.
Fixed File.Encoding
:= x "-RAW" breaking encoding/decoding of non-ASCII
characters. The -RAW suffix is now ignored.
1.1.15.03 - August 2, 2014
Fixed meta-functions to
exit the thread correctly after using Exit or Throw.
Fixed FileInstall to use A_WorkingDir when Dest is relative in a
non-compiled script.
1.1.15.02 - July 7, 2014
Fixed debugging negative integer keys in objects.
1.1.15.01 - June 30, 2014
Changed built-in error and warning dialogs to be always-on-top.
Fixed Until not breaking out of recursive file/registry loops.
1.1.15.00 - May 4, 2014
Added A_OSVersion value WIN_8.1.
Changed the Hotkey
command to apply/remove passthrough behavior on existing hotkey variants
depending on whether the tilde (~)
prefix is present.
Changed exe manifest to allow GetVersion/GetVersionEx to
detect Windows 8.1.
1.1.14.04 - April 25, 2014
Fixed DllCall() crashing
the script when Function is pure integer 0.
Fixed IsFunc("ComObj(") to return false instead of throwing an exception.
Fixed ControlClick to send XButton1/XButton2 correctly.
1.1.14.03
- February 14, 2014
Fixed a memory leak in new X when X.__Init aborts the thread.
Fixed breakpoints shifting onto class var initializers when they
are interspersed with method definitions.
1.1.14.02 - January 30, 2014
Fixed x:: and x up:: both firing on key-up if the state of the modifier keys prevented
x from firing on key-down. The intended
behaviour as of v1.1.14 is for both hotkeys to fire on key-up if x
is also used in a custom combination like x
& y::.
1.1.14.01
- January 15, 2014
Fixed Try without Catch/Finally crashing if no exception was
thrown.
1.1.14.00 - January 15, 2014
Added Finally statement for performing cleanup after try/catch. [fincs]
Changed behaviour of ~ prefix with
custom combos to be more intuitive.
Fixed x
& y:: to fire both
x:: and x up:: when x is released.
Fixed ImageSearch to set ErrorLevel=2, not 0, when a GDI call
fails.
Fixed EnvGet crashing the program when the var exceeds 32767
chars.
Fixed a minor error-handling bug with StatusBarWait's ErrorLevel.
Fixed a cause of heap
corruption with FileRead *c on ANSI builds.
Fixed passing of local vars
in recursive calls to variadic functions.
Fixed script failing to load if the first line is an expression in
parentheses.
Fixed PixelSearch Fast mode to set OutputVarX/Y only on success.
1.1.13.01 - October 11, 2013
Fixed variadic function calls with named values for required
parameters.
1.1.13.00 - August 27, 2013
Ported StrSplit() from v2
alpha.
1.1.12.00 - August 14, 2013
Optional parameters can be omitted by writing two consecutive
commas, as in InStr(a,
b,, 2). Unlike previous versions, this now
works for objects (including COM objects) and
built-in functions. [a,,b] can be used
to create a sparse array.
Object properties can now be set using variadic syntax, as in x[y*]:=z, where y contains an array
of keys/indices or parameters.
1.1.11.02 - July 28, 2013
Fixed GuiControl/Get to accept the ClassNN of a ComboBox's child
Edit. Specifying the HWND of a
ComboBox's child Edit was
already supported as a means of identifying the ComboBox.
1.1.11.01
- June 25, 2013
Fixed InputBox default
width/height (broken by v1.1.11.00 - commit
7373cc6443).
Fixed DllCall arg type validation to handle SYM_OBJECT safely, and
to respect #Warn UseUnset (when var name is not a valid type).
Changed VarSetCapacity(var) to never warn about
uninitialized vars.
1.1.11.00
- June 21, 2013
Added support for %A_LineFile% in #Include.
Reduced the file size of
AutoHotkeySC.bin by reducing the resolution of the (rarely used) filetype icon.
Fixed class X extends Y to allow Y to be defined after X.
Developed by
fincs: AutoHotkey is now DPI-aware. The Gui commands automatically compensate
when DPI is not 96. See Gui -
DPIScale.
1.1.10.01
- May 17, 2013
Improved RegRead to support
REG_BINARY values larger than 64K.
Improved RegWrite to support REG_BINARY/REG_MULTI_SZ values larger
than 64K.
Fixed Process Close (and possibly other things) on Windows XP.
1.1.10.00
- May 11, 2013
Added basic support for custom Gui control types.
Revised SoundSet, SoundGet and
'WaveVolume commands to better support Windows Vista and later.
Fixed Run
"<file>" <args> to not pass the space as
part of the args.
Fixed some issues with
reading from console input (CONIN$).
1.1.09.04
- March 14, 2013
Fixed Gui menu accelerator keys not working when the Gui itself
(not a control) has focus.
1.1.09.03 - February 9, 2013
Fixed two bugs which
affected certain assignments where the target variable contains an unflushed
binary number but has zero capacity. Fixed
GuiControl and GuiControlGet acting on the wrong control when given a HWND
which does not belong to the current Gui.
Instead, the condition is treated as an error.
Fixed OnMessage functions to set A_Gui and A_GuiControl correctly
when the target Gui is a child window.
1.1.09.02 - December 24, 2012
Fixed MsgBox to show an error message when given invalid Options,
instead of silently exiting the thread.
Fixed syntax errors in class var initializers causing the program
to crash without the proper error message.
1.1.09.01 - December 15, 2012
Fixed AND/OR following a multi-statement comma, like ((x, y) and z).
Fixed RegExReplace to support duplicate subpattern names
correctly.
Fixed Object.Remove() not freeing string keys.
Fixed base.Invoke() to not depend on dynamic variable resolution.
1.1.09.00 - November 7, 2012
Breaking changes:
Removed .aut file compatibility and #AllowSameLineComments.
Removed undocumented AutoIt
v2 commands.
Backward-compatible
changes:
Allow optional parameters
to be declared with := instead of =, for consistency with variable declarations and expressions.
Allow non-ASCII characters
in unquoted keys ({key: x} and obj.key).
Changed name in version
info from "AutoHotkey_L" to "AutoHotkey".
Bug-fixes:
Fixed instability caused by
warning dialogs appearing part-way through evaluation of a command's args.
Fixed PixelSearch Fast mode
treating "not found" as an error.
Fixed ahk_exe to allow
other ahk_ criteria after it.
Fixed else continue 2 and similar requiring braces around the loop.
Fixed RegRead indicating
failure after successfully reading binary data.
Fixed File.Length to compensate for or flush any buffered data.
Fixed Gui sizing to account
for scrollbars when present.
Debugger:
Added support for
asynchronous commands.
Improved handling of breakpoints on lines like else foo() or { bar() so that
the debugger will actually break when appropriate.
Optimized code size, fixed several bugs and made the debugger
generally more robust.
1.1.08.01
- August 3, 2012
Debugger: Fixed max_depth being either half the intended limit or
unlimited.
1.1.08.00 - July 14, 2012
Breaking changes:
Changed the default script codepage to ANSI, as the previous
behaviour was a common source of confusion. UTF-8 files must now have
a byte order mark (BOM) to be recognized correctly.
Notepad adds a BOM to any file saved as UTF-8.
Changed return
x to preserve formatting of numeric strings; it is now equivalent
to return (x).
Changed Gui,
Name: New to set the new GUI as the default.
Other changes:
Changed ClipboardAll to
prefer CF_UNICODETEXT over other text formats.
Changed Gui Show to allow
floating-point numbers.
Changed A_OSVersion to
return WIN_8 on Windows 8.
Changed AutoHotkey.exe file
description to include "ANSI/Unicode 32/64-bit".
Changed the parser to allow
lines like new MyObject() with no assignment.
Upgraded PCRE to 8.30.
Improved wording of some warnings and
added a pointer to the documentation at the bottom of the warning dialog.
Improvements to the debugger:
Added
basic support for inspecting Func, ComObject and RegExMatchObject objects.
Fixed the "attach debugger" message being ignored in
some situations. See commit 83f0a0e.
New features:
Added support for the PCRE
construct (*MARK:NAME) via RegExMatchObject.Mark.
Added support for classvar.x
:= y assignments in class definitions (after declaring classvar).
Added A_Is64bitOS.
Added SetRegView and A_RegView.
Fixes:
Fixed Func.() to merely skip the function call if mandatory parameters were
omitted instead of causing the thread to silently exit.
Fixed Object.Remove() not releasing object keys.
Fixed key-down/key-up
hotkey pairs to suppress input correctly when only one hotkey in the pair is
enabled.
Fixed #Include <Lib> to not affect the working directory used by subsequent #include
directives.
Fixed objaddref() acting like ObjRelease() when
called with a lower-case 'a'.
Fixed A_AhkPath in 32-bit
compiled scripts to detect 64-bit AutoHotkey installations and vice versa.
Fixed TreeView controls
with -Background option rendering incorrectly on older OSes.
Fixed error messages shown
during execution of While/Until to identify the appropriate line.
1.1.07.03
- March 25, 2012
Fixed Ctrl/Alt/Shift
key-down hotkey breaking any corresponding key-up hotkey defined before it.
Fixed key-down hotkeys to always use the hook if defined after a
key-up hotkey of the same key. If the key-down hotkey used the "reg"
method, the hook would block the key-down event and
trigger only the key-up hotkey.
Fixed load-time checks interpreting expressions with no derefs as
raw text. For example, gosub
% "foo" resolved to "foo": at load-
time. Similarly, % "" was seen
as invalid in various cases even if an empty string should be allowed.
1.1.07.02
- March 22, 2012
Fixed a rare crash which
can occur when GetClipboardData() fails.
Fixed ComObjArray() to return an empty string on failure instead
of an arbitrary integer.
Fixed Object.Remove(i,
"") affecting integer keys when !Object.HasKey(i).
1.1.07.01 - March 2, 2012
Fixed FileRead to ignore #MaxMem when reading UTF-16 on Unicode
builds.
Fixed dynamic function calls with built-in vars such as %A_ThisLabel%().
1.1.07.00 - February 27, 2012
Enhanced %var%() to
support function objects and the default __Call meta-function.
Fixed ControlGet List to work
for ListViews where the script and the target process aren't both 32-bit or
both 64-bit.
Fixed SendEvent with a key delay of 0; a change introduced by v1.1.05.04 caused
it to be slower than intended.
Fixed Object.Remove(i) not
adjusting keys if Object[i] doesn't exist.
Fixed an error in ComObjType() which
may have caused unpredictable behaviour when it is called via an alternative name.
Fixed ExitApp to exit
the thread if an OnExit
subroutine prevents the script from terminating, instead of resuming execution
after the
block which
contained ExitApp.
Calling a function via an
object no longer acts as a barrier to exiting the thread. Consequently, if Exit is used or
a runtime error occurs
within a class method, the entire thread exits
instead of just the function.
Calling a base-class method using base.Method() or
similar inside a class definition no longer causes a UseUnset warning
if the method doesn't exist. Consequently,
instantiating an object which has instance variables no longer causes a warning about the internal
base.__Init method if the base class
has no instance variables.
1.1.06.02
- February 13, 2012
Fixed IniRead crashing when Section is omitted but Key isn't.
Fixed accuracy of FileGetSize with files which are 4GB or larger.
1.1.06.01 - February 12, 2012
Fixed MsgBox smart comma handling to require numeric Options, not
Title.
1.1.06.00 - February 12, 2012
New features:
Integrated #InputLevel
directive and SendLevel command by
Russell Davis.
Integrated support for Link controls
by ChrisS85.
Breaking changes:
Changed command parser to avoid trimming escaped characters such
as `t or ` at the beginning or end of
an arg.
Changed MsgBox's smart
comma handling to improve flexibility and consistency.
% can now be used to make Options or Timeout an expression.
If the first arg is an expression, any unescaped comma which is
not enclosed in quote marks or
parentheses/brackets/braces will
cause multi-arg mode to be used. These commas were formerly
interpreted as multi-statement operators within the first-and-only
arg (Text).
When Title is an expression, unescaped commas contained within the
expression no longer interfere with smart comma handling.
If there are exactly two args and the first is empty or an
integer, multi-arg mode is used. The former behaviour was to combine
both into a single arg
(Text).
Timeout can be a literal number or a single deref (and optionally part of a number; for example, %Timeout%.500). Contrary to the
documentation, the former behaviour interpreted most other cases
beginning with % as expressions (containing a double-deref).
Title can be an expression even if Text and Options are omitted.
Changed A_IsUnicode/A_IsCompiled to be defined as an empty string
in ANSI versions/uncompiled scripts instead of being left
undefined. This allows them to be checked without triggering #Warn
warnings. Side effects include:
Attempting to assign directly to A_IsCompiled or A_IsUnicode
always causes a load-time error. Dynamic assignments always fail,
either silently or with an error dialog as appropriate. Previously
assignments were allowed in uncompiled/non-Unicode scripts.
Attempting to take the address of A_IsCompiled or A_IsUnicode
always fails.
A_IsCompiled and A_IsUnicode no longer appear in ListVars when
referenced by a script which is not compiled/Unicode.
Changed Send and
related commands to respect #MenuMaskKey when
changing modifier keystates.
Other changes:
Changed GuiControl Choose to
remove the ListBox/ComboBox/DDL's current selection when N=0.
Changed RegisterCallback to allow
a Func object in place
of a name.
Changed ListLines to show filenames (except when compiled).
Improved Run to
output a process ID if possible when ShellExecuteEx is used.
Fixes:
Fixed handle leaks in
RegRead.
Fixed x.y++ and
similar to assign an empty string if x.y is non-numeric.
Fixed SendInput Win+L
workaround causing Win key to "stick down".
Fixed Ahk2Exe
auto-including the wrong file if an auto-include used #Include <Lib>.
1.1.05.06
- December 31, 2011
Fixed inc (++) and dec (--) having no effect when used on an
object field containing a string.
Fixed inc (++) and dec (--) to cause a warning when used on an
uninitialized variable.
1.1.05.05 - December 17, 2011
Fixed continue n misbehaving when an inner loop has no braces.
Fixed RegExMatchObject[Name] to work correctly with duplicate names.
1.1.05.04 - December 5, 2011
Fixed: Selected sub-command
of ControlGet was unreliable on x64.
Fixed: CPU was maxed out while waiting if an underlying thread
displayed a dialog (and possibly in other cases).
1.1.05.03 - November 30, 2011
Fixed Loop
... Until VarContainingObject.
1.1.05.02 - November 20, 2011
Fixed false detection of
end-of-file when loading a compiled script in some cases.
Fixed SendInput to automatically release modifier keys when
sending special characters or {U+xxxx} (which was broken by v1.1.00.01).
Fixed ComObjConnect to filter out non-dispatch
interfaces instead of allowing the script to crash.
Fixed new %VarContainingClassName%().
1.1.05.01
- October 16, 2011
Fixed class declarations to allow directives such as #Include.
1.1.05.00 - October 8, 2011
Added Client coordinate mode.
Added object output mode for
RegExMatch and RegEx callouts.
Added super-global
declarations, which avoid the need to repeat global declarations.
Breaking change: Class
declarations such as Class
c now create a super-global variable instead of an ordinary global.
Added more detail to unhandled exception error dialogs.
Changed Gui +Owner to work
even after the GUI is created.
Changed instance var declarations in class definitions to avoid
leaving empty key-value pairs in the class object.
Changed #Include to use standard error message formatting when it
fails (more detail; also respects ErrorStdOut).
Changed Throw to throw
an Exception object by default when its parameter is omitted.
Changed format of runtime
error messages slightly to improve consistency and code size.
Modified PCRE to use UTF-16
for input on Unicode builds, for performance.
Upgraded PCRE to 8.13.
Fixed thread not exiting as
intended when an assignment in an expression fails.
Fixed #MaxMem preventing
assignments to variables which don't require expansion.
Fixed inability of
Try/Catch to catch COM errors.
Fixed GuiControlGet
incorrectly treating parameter #2 as invalid in some cases.
Fixed input vars being resolved too soon, allowing them to be
invalidated by an expression later on the same line.
Fixed RegEx callouts not causing matching to abort when an
exception is thrown.
Fixed DllCall setting
ErrorLevel to -4 when it should be -3.
Fixed While appearing twice
in ListLines for its first iteration.
Fixed Try/Catch to allow
If/Loop/For/While with no enclosing block.
Fixed enumerator object not
being released when Until is used to break a For-loop.
1.1.04.01
- September 15, 2011
Fixed FileRemoveDir setting ErrorLevel incorrectly.
1.1.04.00 - September 11, 2011
Warning: This release contains a number of
potentially script-breaking changes.
Added exception handling
support: try/catch/throw and Exception().
Added StdOut mode for #Warn.
Added Gui +HwndVARNAME option.
Added Gui, New [, Options, Title].
Added automatic support for
keyboard accelerators such as Ctrl+O in Gui menus.
Changed handling of #Include <Lib> when the /iLib command-line switch is present to resolve a problem with Ahk2Exe.
Changed GuiControl to retain the Progress control's current value
when its style is changed.
Changed GuiControl and
GuiControlGet to allow a HWND to be passed in the ControlID parameter.
Removed the 1GB limit from
FileRead.
Improved error detection:
Hotkey, If, Expression, where Expression does not
match an existing #If expression, is caught at load-time when possible.
Hotkey, IfSomething, where Something is invalid, is caught at load-time.
Class definitions with missing braces are detected as errors.
If a function call is used on the first line of a class
definition, it is now correctly treated as an error.
GroupAdd now shows an error message when the group name is blank,
instead of silently exiting the thread.
Removed some redundant "unset var" warnings which
appeared when using the OutputDebug or StdOut warning modes.
If an unrecognized option is used with Gui, Gui Show, Gui New or GuiControl, an
error message is shown and the thread exits
unless try is used.
This validation is not done at load-time due to complexity (it is common for
the option parameters to contain
variable references).
RegRead, RegWrite and RegDelete now set A_LastError to the result
of the operating system's GetLastError() function.
+LastFoundExist is now treated as an error if it is combined with another option
(+LastFound should be used in that case).
Fixed a bug
affecting recursive variadic functions.
1.1.03.00 - August 28, 2011
Added support for GUI
names.
Added support for
identifying a GUI by its HWND.
Added +Parent%ParentGui% Gui option.
Added support for external windows as Gui owners via +Owner%HWND%.
Added Name sub-command for GuiControlGet.
Added support for ActiveX
controls via the Gui command.
Fixed: Empty hotkey control
returned "vk00".
Fixed: Crashes and memory leaks related to COM
events/ComObjConnect.
Fixed: GuiControlGet OutputVar, Subcmd, %OutputVar% always failed.
Changed "Missing (/[/{" error messages to "Unexpected
)/]/}" for greater clarity.
Changed ListLines to
display While and Until lines which are executed each iteration.
Changed ~= to have higher precedence than
=/!=/</>/<=/>= but lower than concat, and added it to the
documentation.
1.1.02.03 - August 21, 2011
Fixed (Debugger): numchildren attribute did not include
Object.Base.
1.1.02.02 - August 20, 2011
Fixed: Variable capacity was capped at 2GB on x64 builds.
Fixed: Last Found Window not set by #if WinExist(T).
1.1.02.01 - August 13, 2011
Changed A_PriorKey to
exclude key-up events.
Fixed process name/path
retrieval in certain cases, including:
Retrieving
name/path of a 64-bit process from a 32-bit script.
Retrieving name/path of an elevated process from a non-elevated
process (UAC).
1.1.02.00
- August 6, 2011
Added TV_SetImageList().
Characters which require non-standard shift states 16 and 32 now
use a fallback method instead of producing the wrong keystrokes.
Revised handling of dead keys to solve problems which
occur when multiple scripts with hotstrings are active.
1.1.01.00
- July 30, 2011
Added support for instance
variables in class definitions, using simple assignment syntax.
Removed var keyword used in class
definitions; use static instead.
Added new built-in
variables: A_ScriptHwnd and A_PriorKey.
Added new built-in
functions: GetKeyName(), GetKeyVK(), GetKeySC() and IsByRef().
Added new sub-command:
WinGet, OutputVar, ProcessPath.
Added the capability to specify a window by process name or path: ahk_exe
%Name%.exe or ahk_exe
%FullPath%.
Optimized ProcessName sub-command of WinGet.
Changed SetTimer to use
A_ThisLabel if Label is omitted.
Updated ComObjConnect() to
support using an object in place of a function name prefix.
Improved ComObjConnect() to
allow the prefix/object to be updated without first disconnecting.
Improved parsing of
continuation sections to allow expressions like (x.y)[z]() without escaping "(".
Replaced the method used to
store script text in 32-bit compiled scripts; now consistent with 64-bit.
Fixed detection of AltGr in
the active window's keyboard layout (on Unicode builds).
Fixed SendInput applying a
redundant LCtrl-up some time after AltGr-up.
1.1.00.01
- July 17, 2011
Fixed: Modifier keys
weren't auto-released when sending special chars.
Fixed:
Scancode/modifier-key mapping conflicts such as sc1xx vs ^sc0xx.
Fixed: $ and #UseHook had
no effect if used only on the second or subsequent instance(s) of a hotkey.
Fixed: Potential crash when
returning a value from a __Delete meta-function.
Fixed: "Uninitialized
variable" warnings were triggered by the debugger.
Changed: base.Method() no longer triggers a
default meta-function or a warning.
Changed: Gui +(Ex)Style no longer hides/shows the Gui.
Changed the debugger to
report type="undefined" for uninitialized variables.
Added check to avoid incorrectly sending keystrokes for characters
which actually require the "hankaku" key.
Added support for integers as class variable names.
Added "Static"
keyword for declaring class variables.
1.1.00.00
- May 1, 2011
New features:
Implemented basic class definition syntax.
Implemented the new keyword for creating a derived object.
Added Func() for
retrieving a reference to an existing function and improved IsFunc to
recognize function references.
Added support for ++ and -- with object fields, such
as x.y[z]++.
Changes:
Changed __Delete to not
trigger __Call.
Changed OnClipboardChange to use AddClipboardFormatListener when
available (i.e. on Windows Vista and later) to improve reliability.
Auto-concat with ( is more selective, so some invalid expressions like 12(34) will no longer work.
Fixes:
Fixed SetTimer Label, -0 to be treated as "run-once, very soon".
Fixed A_MyDocuments etc. to
use SHGetFolderPath instead of undocumented registry keys.
Fixed non-empty ExcludeText
causing windows with no text to be excluded.
1.0.97.02
- April 14, 2011
Fixed misinterpretation of
comma as an arg delimiter when enclosed in {} in an expression.
Fixed For-loop to set
A_Index only after the Expression
arg is evaluated, so that the outer loop's value can be used.
Fixed default script location to be based on the directory
containing the EXE (as documented), not the working directory.
Improved load-time validation to detect invalid attempts to jump
out of a function with Goto.
1.0.97.01
- April 2, 2011
Fixed the 64-bit build to not truncate HWNDs or
SendMessage/PostMessage params to 32 bits.
Fixed */:: being treated as an
invalid hotkey (broken since L54).
Fixed the icons.
1.0.97.00
- March 28, 2011
Added {key:
value} as syntax sugar for Object("key",
value).
Added [x, y, z] as syntax sugar for Array(x,
y, z), which is a new function equivalent to Object(1, x, 2,
y, 3, z).
Added slight optimization: resolve any reference to True, False,
A_PtrSize or A_IsUnicode in expressions at load-time.
Fixed hotkey parser to
treat x & ^y as an error instead of ignoring
^.
1.0.96.00
- March 21, 2011
New features:
ComObjQuery: Queries
a COM object for an interface or service.
ComObjFlags:
Retrieves or changes flags which control a COM wrapper object's behaviour.
ComObjCreate allows
non-dispatch objects to be created if an interface identifier (IID) is given.
COM arrays support for-loops and the Clone() method.
ListVars shows the inner
variant type and value of each COM wrapper object, in addition to the wrapper's
address.
Changes:
When a literal integer or variable containing both a numeric
string and cached binary integer is assigned to a field of an object, an
integer is stored instead of a string.
This particularly benefits scripts calling COM methods which accept integers but
not strings, or have
different behaviour depending on the type of value.
NULL values are now allowed
with ComObjParameter for the VT_UNKNOWN and VT_DISPATCH types.
Improved support for Common
Language Runtime (.NET) objects via COM.
FileRecycle should now warn
before deleting a file which is too large to recycle.
When a SafeArray created with ComObjArray is assigned to an
element of another SafeArray, a separate copy is created. This prevents
the script from crashing due to a second attempt at
"destroying" the array. ComObjFlags allows this behaviour to be
avoided.
Fixes:
Assigning to a COM array of
VT_DISPATCH or VT_UNKNOWN crashed the script.
Break and Continue were
tolerated outside of loops in some cases.
Standalone carriage-return
(`r) was not correctly interpreted as end-of-line.
MouseMove miscalculated
negative coordinates with the Input and Event send modes.
Selecting Edit This
Script from the tray menu or using the Edit command crashed the script (broken
by v1.0.95).
Error dialogs pointed at irrelevant lines of code in some cases.
1.0.95.00
- March 12, 2011
All file I/O has been
heavily optimized.
Added #Warn to
assist with debugging; initial design by ac.
By default, if name_var contains a function name, name_var.() calls the function. This can be overidden via the default base object, as before.
Run supports verbs with
parameters, such as Run
*RunAs %A_ScriptFullPath% /Param.
If an operator which can accept either one operand (&x) or two numeric
operands (x & y) follows a quoted literal
string, auto-concat
occurs and the operator is applied only to the right-hand operand.
This is because quoted literal strings are always considered non-
numeric and are therefore not valid input for numeric operators.
For example, expressions like "x"
&y and "x" ++y now work.
Fixed:
Wildcard hotkeys were not respecting modifiers such as ^!+ in specific cases.
File.Pos returned garbage for non-seeking file types; now it
returns -1.
File.AtEOF was incorrectly true in some cases.
COM wrapper objects left A_LastError unset in some cases.
Gui submenu icons did not work on Windows 2000/XP/Server 2003.
SplashImage clipped the image if height > width.
ComObjConnect did not alert when the first parameter is invalid.
SplashImage now uses GDI+ only when the other methods fail, for
compatibility.
Tilde in ~x:: now affects x & y:: in the
same way that ~x & z:: would, instead of having
no effect.
A_PriorHotkey and A_TimeSincePriorHotkey now have the expected
values when used with #If.
RegExReplace did not advance through the string correctly after a
match failure if the string contained non-ASCII characters.
1.0.92.02
- January 19, 2011
Fixed a memory leak which occurred when the return value of an
object invocation or built-in function was not used, such as
file.ReadLine() or SubStr(x,y,z) alone on a line.
Replaced the fix from v1.0.92.01 with a better fix, which also
fixes k::MsgBox(),x:=y and doesn't break if().
1.0.92.01 - January 18, 2011
Changed: FileCreateDir now
sets A_LastError.
Fixed: GuiControl() or
similar was sometimes misinterpreted as a command.
1.0.92.00 - January 13, 2011
Added support for compound
assignments with objects, such as x.y +=
z.
Improved IniWrite in Unicode builds to prevent an empty line from
appearing at the top of each new file.
Improved the parser to be more permissive about what can follow {/}/Else, especially when combined.
1.0.91.05 - January 1, 2011
Fixed: Cleanup code in COM method calls was freeing the wrong
parameters.
Fixed (ANSI): DllCall set incorrect length for WStr parameters on output.
Fixed: Variadic function calls were unstable when param object was
empty.
1.0.91.04 - December 29, 2010
Fixed (Unicode): RegExReplace omitted all text up to
StartingPosition (broken by v1.0.90.00).
1.0.91.03 - December 27, 2010
Fixed: RegEx callout subpattern vars - broken by v1.0.90.00.
1.0.91.02 - December 26, 2010
COM: Added protection
against NULL IDispatch/IUnknown pointers.
COM: Skip QueryInterface
for IDispatch if VT_DISPATCH is passed explicitly.
Minor fix for maintainability: obj.field := var now correctly yields SYM_STRING, not SYM_OPERAND.
1.0.91.01 - December 24, 2010
Fixed: Unexpected results
with File.Write(Str) after text-reading.
Fixed: UTF BOM check caused
unexpected results in files without a BOM.
Fixed (ANSI): Parsing loops
and File.ReadLine() treated Chr(255) as EOF.
Fixed (Unicode): RegExReplace errors where the UTF-8 and UTF-16
lengths differed.
Fixed: Disabling the last hook hotkey breaks Input.
Added: Simple optimization
for RegExMatch/Replace.
1.0.91.00
- December 21, 2010
All changes in this release
are COM-related.
Added: ComObjError now
returns the previous setting.
Added: ComObjType(co) and ComObjValue(co).
Added: ComObjMissing().
Added: ComObjArray() and
basic SAFEARRAY support.
Added: "Take
ownership" parameter for ComObjParameter().
Changed: Values passed to COM functions via ComObjParameter are no
longer freed in the process of calling the function.
Changed: ComObj.x() now falls back to PROPERTYGET if member 'x' is not found. This
fixes for-loops for some objects.
Changed: Wrap unhandled variant types in an object rather than
returning integer value.
Changed: Manage
VT_UNKNOWN/VT_ARRAY lifetime automatically, by default.
1.0.90.00
- November 27, 2010
Fixed: UrlDownloadToFile in
Unicode builds on Windows < 7.
Fixed: Upper-ANSI
characters were sent as Alt+0 in ANSI build.
Fixed: File.Pos was
incorrect after attempting to read past EOF.
Fixed: Escape sequences in
#If expressions and static initializers.
Fixed: ClipboardAll
sometimes crashed the script with certain formats.
Fixed: Transform HTML calculated length incorrectly for &#NNN;
entities.
Fixed: VarSetCapacity now correctly ignores #MaxMem for ByRef
variables.
Fixed: FileAppend,,file.txt set
ErrorLevel=1 even on success.
Fixed: Match length was miscalculated for RegEx callouts with the
P) option.
Integrated Sean's improvements to number handling in COM interop.
Optimized RegExReplace and RegExMatch in Unicode builds.
Revision 61 - October 3,
2010
Added: ObjClone(Object), forgotten when Object.Clone() was
implemented.
Added: Support for RegEx
Unicode properties in Unicode builds. Also upgraded PCRE to 8.10.
Added: Object.Remove(int,
"") removes Object[int] without affecting other keys.
Changed: ComObj.xyz() is now always treated as a method-call.
Changed: Var :=
123 is now left as an expression, for consistency. This makes Var :=
123 and Var := (123)
equivalent, whereas previously the former assigned
only a string and the latter assigned both a string and a cached binary
integer. In particular, this avoids some
confusing type mismatch errors with COM objects.
Fixed: Dynamic variadic
calls to functions with mandatory parameters.
Fixed: The final parameter of an assume-global variadic function
had to be explicitly declared local.
Fixed: Static initializers interfering with setting of
breakpoints.
Fixed: More pointer
size-related errors with PCRE callouts on x64 builds.
Fixed: Input with 'M'
option treated Ctrl-M (`r) as Ctrl-J (`n).
Fixed: Object.Remove(n) returned 0 (not "") if
Object[n] didn't exist.
Revision 60 - September 24,
2010
Added: File.Encoding for
changing or retrieving the codepage in use by a File object.
Added: Variadic functions and function-calls and indirect mode for
callbacks.
Added: Object.Clone()
Changed: ByRef parameters
no longer require the caller to supply a variable.
Changed: Obj.foo := "" now frees foo's contents as originally intended (but still
doesn't remove the field).
Changed: OnMessage
functions now tolerate optional and ByRef parameters.
Changed: RegisterCallback
now enables execute access on callbacks in 32-bit builds (already did in 64-bit
builds).
Changed: RegisterCallback
now treats explicit ParamCount="" as omitted.
Fixed: For-loop was
treating non-expression "0" as true for scripted enumerators.
Fixed: ComEvent
(ComObjConnect) not working on the ANSI build.
Fixed: ComEvent (ComObjConnect) not correctly backing up/restoring
local vars when calling a function which is already running.
Fixed: Buffer overflow in A_EndChar when there is no end char.
Fixed: Func->mNextFunc
not inititialized to NULL (used only by LowLevel scripts).
Debugger: Added the
capability to retrieve an object's contents (with a supported debugger client).
Debugger: Fixed a few bugs.
Revision 59 - September 12,
2010
Fixed: #If expression should now evaluate each expression at most once per keypress in all cases.
Changed: SplashImage uses common image-loading routines; now
supports PNG and similar, but results may differ from before for icon
files.
Added: For x,y
in z.
Added: Loop
.. Until expression, usable with any Loop or For-loop.
Added: Named loops; continue
outer_loop, break 2, etc.
Debugger: Encode stdout and
stderr packets as UTF-8.
Debugger: Allow user to
Abort, Retry or Ignore when the initial connection fails.
Debugger: Allow attaching a debugger client by sending the script a registered window message.
Debugger: Allow detaching debugger client by sending the
"detach" DBGp command.
Revision 58 - September 5, 2010
Added: static var := expression.
Revision 57 - September 4, 2010
Fixed Str*, WStr* and AStr*
DllCall return types on x64.
Added functionality to InStr to bring
it in line with StringGetPos:
If StartingPos is negative, the search is conducted right-to-left
beginning at that offset from the end.
An additional parameter is available to specify which occurrence
of the string to find.
Added #include
<LibName> for explicitly including a script from a function library folder.
Added functionality to IniRead and IniWrite allowing
an entire section to be read or written.
Added functionality to IniRead allowing
a list of section names to be retrieved.
Added support for custom verbs to Run/RunWait: Run *verb file.
Made improvements to the way Run/RunWait extracts the action and its parameters
from the Target parameter.
Changed NumGet/NumPut to allow Offset to be omitted entirely since Type is always
non-numeric.
Removed the restriction
that a label can't point to the end of a block.
Revision 56 - August 29,
2010
Added support for x64 compiled scripts. Requires Ahk2Exe_L and x64
AutoHotkeySC.bin.
Fixed: Deref operator (*addr) rejected addresses outside 32-bit range.
Fixed: #If expression memory
allocation error on x64.
Fixed: Custom hotstring end
chars with code points greater than U+00FF.
Fixed: Special characters
being sent out of sequence by SendInput/Play.
Fixed: */ being discarded in continuation sections (see L54).
Revision 55 - August 19,
2010
Fixed: GroupActivate not
setting ErrorLevel=1 if no Label was specified.
Fixed: Tab controls in x64
build.
Fixed: String-copy mode of
StrPut when length is omitted; broken by L53.
Fixed: Data-alignment
issues in x64 builds.
Changed: Set A_LastError
for more File* commands to assist debugging.
Includes FileAppend, FileRead, FileReadLine, FileDelete, FileCopy,
FileMove, FileGetAttrib/Time/Size/Version and
FileSetAttrib/Time.
Excludes FileCopyDir, FileRecycle, FileMoveDir, FileRemoveDir,
FileRecycleEmpty, FileCreateDir and FileInstall as the APIs used do
not consistently set or return a Win32 error code.
Revision 54 - August 15,
2010
Fixed: RunAs in Unicode
build. [jackieku]
Fixed: RegisterCallback in
x64 build. [fincs]
Fixed: Executables failing to run on Win2k and WinXP prior to SP2.
Win2k requires SP4 and updates (probably KB 816542). XP not
tested.
Fixed: Dialogs such as MsgBox became unresponsive when interrupted
by another script thread. Message filter/workaround added in
L45 had to be removed.
Fixed: Multi-byte characters in default ANSI codepage; this was
also causing a memory leak.
Fixed: ComObject now allows purely numeric property/method names.
Enhanced usability and
capabilities of FileOpen/File object.
FileOpen's
Flags parameter accepts a
human-readable string of flags.
FileOpen's "update" mode has been renamed
"read/write" and now creates the file if it didn't already exist.
FileOpen sets A_LastError as appropriate.
File
:= FileOpen(handle,"h") wraps an existing file
handle in an object.
File.Seek(n) defaults to SEEK_END when n is negative.
File.Pos (or File.Position) can be used in place of
Tell and Seek.
File.Pos, File.Length, File.AtEOF and File.__Handle can be used without empty parentheses().
File.Length can be set, as in File.Length:=n.
File.ReadNum() and File.WriteNum(n) read or write a number, where Num is a NumGet-compatible type
name.
File.WriteLine(s) is equivalent to File.Write(s
"`n"), for symmetry with File.ReadLine().
File.Read() reads and returns the remainder of the file when used without
parameters.
File object now returns "" for unrecognized methods and
invalid syntax rather than the numeric address of "".
Changed: GroupAdd's Label parameter now applies to the whole
group. [Discussion]
Changed: GroupActivate sets ErrorLevel on success/failure. (Same
thread as above.)
Changed: */ at the beginning of a line is ignored if there was no /*. [Discussion]
Removed ToCodePage and FromCodePage subcommands of Transform.
Revision 53 - August 8, 2010
Merged AutoHotkey64 - COM support and x64 compatibility.
x64 (changes since
AutoHotkey64):
Fixed floating-point return values and exception handling for
DllCall.
Fixed RegEx callouts.
Re-enabled GetProcAddress optimisation for DllCall.
NumPut and NumGet default to "Int64" in x64 builds.
COM (changes since AutoHotkey64):
Allow
ComObjParameter to wrap 64-bit values in 32-bit builds.
Implemented more standard ref counting conventions in
ComObjActive.
Prevent extraneous AddRef for new ComObjects in certain cases.
Don't treat pdispVal==NULL return value from Invoke as an error.
Fail more predictably when given wrong type of object.
Require explicit second param in ComObjType, don't assume
"IID".
Free local vars after ComEvent calls a function.
Remove pVarResult param from ComEvent; use return value instead.
Pass the original wrapper ComObject in each ComEvent call.
Add context to ComError dialog; let the buttons make more sense.
Implemented common syntax validation code for enumerators. Enum[] and Enum.Next() are now supported with or
without parameters. Enum[]:=val and similar obscure forms
which worked in AutoHotkey_COM/AutoHotkey64 are not allowed.
"Ptr" type is
still signed (unlike AutoHotkey64), for maximum flexibility and consistency.
Other changes:
Added: Object.HasKey(key).
Added: Object(obj) increments obj's reference count and returns its address.
Added: ObjAddRef() and ObjRelease().
Fixed: A_ThisHotkey now has
the expected value when used with #If.
Fixed: RunAs in Unicode
build (fixed by jackieku).
Changed: Default script
codepage for ANSI builds is now CP0 (ANSI).
Changed: x.y[] is now
equivalent to (x.y)[] rather than x["y"].
Changed: Built-in methods can now be called with or without the
underscore prefix (e.g. obj.MaxIndex() or obj._MaxIndex()).
Revision 52 (again) - July 10, 2010
Added support for built-in
and environment variables in double-derefs.
Improved support for multi-byte characters in certain codepages
(previously only 932, 936, 949, 950 and 1361 were supported).
Fixed: StrPut failed for codepages which don't support
WC_NO_BEST_FIT_CHARS, such as UTF-7.
Fixed: Double-deref as
object - literal%var%.literal.
Fixed: StrPut("",
Encoding) null-terminated an invalid address.
Revision 52 - June 12, 2010
Fixed: ObjRemove's Key
parameter is now optional, as with Object._Remove.
Fixed: Files were improperly locked while reading, unlike in older
versions.
Fixed: Uppercase Hex format caused negative integers to become unsigned.
Fixed: RegExMatch was corrupting output array items when specific
conditions were met. See bug report.
Revision 51 - April 11,
2010
Changed: Use <EXENAME>.ahk instead of AutoHotkey.ini or
AutoHotkey.ahk.
Changed: Default to UTF-8 for script files; override with /CPnnn.
Fixed: Unpause when the script exits so that object __Delete
meta-functions can run.
Revision 50 - March 27, 2010
Improved flexibility of Object._Insert.
Object._Insert(x) - inserts x at _MaxIndex()="" ? 1 :
_MaxIndex() + 1.
Object._Insert(i,x,y,z) - inserts x,y,z at i,i+1,i+2.
Improved flexibility of Object._Remove.
Object._Remove(k) - removes and returns the
value associated with k.
Object._Remove() - removes and returns the
value at _MaxIndex().
Added file share mode flags
to FileOpen [by jackieku].
Fixed: 'P' option of RegExMatch incorrectly output 1 for
subpatterns which did not match anything.
Fixed: Object._SetCapacity(key,n) was not
null-terminating in some cases.
Fixed: StatusBarGetText
returned only half of the text in Unicode builds.
Revision 49 - March 14,
2010
Added obj._NewEnum().
Added ObjMethod(obj) for each
built-in obj._Method().
Changed: ObjSet/Get/Call
can no longer be called/overridden by script.
Fixed: Potential crash
caused by VK_PACKET check added in L48.
Fixed: Character codes in VK_PACKET events were potentially
misinterpreted as scancodes.
Fixed: ExcludeText was ineffective after the first matching
control.
Revision 48 - February 21,
2010
Fixed: Standalone obj.() was not recognized as a valid expression.
ControlSend now uses WM_CHAR to support characters which have no
associated keycode. For instance, this applies to "…" (en-US),
"∞" in a Unicode build and {U+221e} in either build.
KeyHistory now shows the full 16-bit character code for VK_PACKET
(VK=E7) events. Send may
indirectly cause these to be
generated for Unicode characters.
Revision 47 - February 13,
2010
Fixed (Unicode): ControlGet,List with ListView controls.
Revision 46 - February 11, 2010
Added A_FileEncoding, which returns the current default file
encoding.
Added StrPut and
extended StrGet with
additional features.
Revision 45 - February 8,
2010
Added _GetAddress; _SetCapacity/_GetCapacity may now operate on a
given field. [more info]
Added workaround for WM_PAINT infinite loop often caused by
subclassing.
Allow obj.() as a means to call the default method of an object; equivalent to obj[""]().
Dev: Added solution and
project files for MSBuild 4.0 & VS2010. [more info]
Fixed (Unicode): 'Running'
column in ListHotkeys.
Revision 44 - February 7,
2010
Fixed: Attempting to set
"nothing" crashed the script. For instance, x[]:=z.
Fixed (Unicode): Unable to
find default script (Documents\AutoHotkey.ahk).
Fixed (Unicode): A_Desktop, A_ProgramFiles and several other
built-in variables which read their value from the registry caused strings
to be incorrectly terminated.
Fixed (ANSI): Characters in the range 0x80-0xFF couldn't be found
by InStr or StringReplace.
Changed (ANSI): Treat ToCodePage/FromCodePage like other
unsupported/invalid subcommands.
Revision 43 - January 29, 2010
Fixed: obj.Func() resulting in a random integer when it should be
an empty string.
Revision 42 - January 28, 2010
Merged with AutoHotkeyU.
Numerous bug-fixes and improvements, some relating to the merge.
Revision 41 - December 20, 2009
Fixed: Floating-point numbers were equivalent to an empty string
when used as keys in objects. They
are now converted to numeric
strings in the current float format, as
originally intended.
Revision 40 - December 13,
2009
Changed meta-functions and multi-param behaviour to improve
flexibility. Meta-functions are now invoked *before* searching for an
appropriate field in each base object; however, values in x.base
will override meta-functions defined in x.base.base. Chaining meta-
functions (inheritence) is now possible by avoiding
"Return"
Improved Default Base
functionality to be more consistent with real objects.
Changed (Debugger): While
stepping through code, skip all braces except those which end a function.
Changed (Debugger): When stepping onto the hidden "Exit"
at end of the script, consider it to be *below* the last physical line to avoid
confusion.
Revision 39 - December 2,
2009
Fixed (Debugger): Error in Base64 decoding used by property_set.
Revision 38 - November 17, 2009
Added: #MenuMaskKey directive to change which key is used to mask Alt/Win keyup
events. See this thread for
background
information.
Changed: If x[1,2]:=3 creates an object for x[1], it's base is no longer
automatically set to x.base. See the documentation for a
method of controlling this behaviour.
Revision 37 - November 7,
2009
Added: Support for obj[method_name](params) object-call syntax.
Revision 36 - November 4, 2009
Changed: If x.y or similar is immediately followed by an open-bracket ([), the
right-most identifier preceding the bracket is treated as
the first parameter of the operation. For instance, a.b.c[d] is equivalent to ObjGet(a.b,"c",d) and x.y[z]:=v is equivalent to
ObjSet(x,"y",z,v).
Previously each sub-expression preceding a bracket was evaluated separately.
Changed: If a method-call such as
x.y() is followed immediately by an assignment, the
parentheses are treated as brackets. For instance, x.y(z):=v is now equivalent to ObjSet(x,"y",z,v).
Fixed: If(expr) and While(expr) with no delimiting space or comma.
Revision 35 - October 25, 2009
Fixed: Standalone expressions beginning with two or more
"dots", such as x.y.z(). (Broken by L34.) Note that '(' or '[' or ':=' is still
required.
Revision 34 - October 24,
2009
Changed: Setting a value within an object to an empty string now
stores the empty string rather than removing the key-value pair from
the object. _Remove can still be used to completely remove
key-value pairs.
Changed: Command names must be terminated with a space, tab or
comma. The following characters no
longer bypass this requirement: <>:+-*/!~&|^[]. For instance, syntax errors such as MsgBox< foo and If!foo are now caught at load-time.
Fixed: Return now properly handles expressions which result in a
variable containing an object. For instance, Return x:=y, Return (x), Return
x,... and similar should work now (Return x already worked).
Fixed: Multi-parameter get/set did not correctly support
meta-functions for multiple objects (such as for x and x[y] in the expression
x[y,z]).
Fixed: Cascading object-assignments such as the x[y]:=z in r:=x[y]:=z could not yield numbers or objects - broken by L33.
Fixed: x._Remove(y) crashed
the script or removed the wrong item if x did not contain y.
Fixed: x.=y, if x.y=... and similar. May
affect other expressions.
Fixed: Standalone ternary
expressions no longer requires spaces. For instance, x? F(1) : F(2) is now allowed.
Debugger: On script exit, disconnect debugger *after* releasing
objects to allow debugging of __Delete handlers.
Revision 33 - October 3, 2009
Fixed: Local variables were
not automatically freed for functions which return objects or pure numbers.
Fixed: Two separate
reference-counting errors related to ternary operator and Object().
Fixed: If a string returned by a scripted object function was assigned
directly to a variable, the variable's length was set incorrectly.
Fixed: If the last operation in an expression retrieved a string
from a temporary object, the object and string were freed prematurely.
Fixed: Numeric strings with special formatting were not preserved
when returned from a function via a variable or passed to a recursive
function.
Fixed: If the final result of an expression (other than for
Return) is an object, correctly yield an empty string instead of silently
aborting
the thread.
Fixed: __Delete
meta-functions sometimes overwrote temporary values in the deref buffer.
Added: An address retrieved via &object may be cast back into
an object reference by using Object(address).
Revision 32 - September 26, 2009
Fixed: Send/PostMessage crash when less than three parameters were
specified.
Revision 31 - September 26, 2009
Added: Object/array support
and numerous minor changes to make this possible.
Added: Support for
While(expression) with no delimiting space.
Added: Trim, LTrim, RTrim.
Added: A ~= B; equivalent
to RegExMatch(A, B). May be removed in a future revision.
Fixed: An incompatibility
with LowLevel.
Changed: Characters [, ]
and ? are no longer valid in variable names. Consequently, ? (ternary) no
longer requires a space on either side. Changed: Optional parameters may now be omitted at any
position in the parameter list of a non-dynamic function call. Since this works
by automatically inserting the parameter's default
value at load-time, it is not supported or allowed for dynamic function-calls.
Debugger: Various minor
changes to make program flow easier to follow while stepping through code.
Optimization: If DllCall's first parameter is a literal string
which identifies a function already present in memory, it is replaced with the
actual address of the function.
Updated from v1.0.48.03 to v1.0.48.04.
Revision 30 - May 31, 2009
Updated from v1.0.48.02 to v1.0.48.03.
Revision 29 - May 2, 2009
All supported image formats may now be used as menu icons. Currently it is necessary to specify
"actual size" when setting the icon to preserve transparency on Windows Vista and later. For
example:
Menu, Icon, MenuItemName, Filename.png,, 0
Revision 28 - May 2, 2009
Improved average-case performance of dynamic function calls by
implementing binary search for function name look-ups. This change
also applies to other areas, such as load-time
resolution of function references in expressions and run-time resolution by
OnMessage,
RegisterCallback, etc.
Revision 27 - April 26,
2009
Updated from v1.0.48.00 to v1.0.48.02.
Revision 26 - April 11, 2009
Fixed: Menu icons were not
drawn on items which have sub-menus if owner-drawing was in use.
Fixed: Menu icons were not
freed if all menu items were deleted at once.
Changed (Source): Renamed AutoHotkey.sln to AutoHotkey_L.sln to
allow VS window to be identified more easily.
Revision 25 - March 30, 2009
Fixed: Send {U+xxxx} correctly sets modifier key-state as with any
normal key.
Fixed: Send {U+..xx} no longer triggers hotkey SCxx.
Revision 24 - March 30,
2009
Added: Support for Send {U+xxxx}. SendInput() is used where
available for proper unicode support, otherwise falls back to
Alt+Numpad.
Revision 23 - March 30,
2009
Fixed: GuiControl,
Enable/Disable now only resets focus if the focused control was disabled.
Revision 22 - March 26,
2009
Optimized If var [not] in/contains MatchList, especially for long
lists containing shorter fields.
Revision 21 - March 16, 2009
Minor optimizations to
While. [thanks Chris]
Fixed (Debugger): Revisions
19 and 20 omitted timer threads from the call stack.
Fixed (Debugger):
XML-reserved characters were not escaped in most situations.
Fixed (Debugger): Incorrect command and transaction_id were used
in the final response before exiting the script.
Revision 20 - February 27, 2009
Changed: If an icon cannot be loaded with the new method, fall
back to the old method.
Revision 19 - February 26, 2009
Added: Gui, Font, qN option
to set font quality/control anti-aliasing, where N is between 0 and 5.
Fixed: IL_Add now loads
icons at the most appropriate size when multiple sizes exist.
Merged with AutoHotkey v1.0.48, introducing bug fixes,
optimizations and other changes by Chris. Some AutoHotkey_L features were
integrated into the mainstream release; changes to
these features since previous revisions are as follows:
Legacy behaviour is no longer applied to While - e.g. "While
%x%" is correctly interpreted as a double-deref rather than as "While
x".
One-True-Brace style is now supported for While.
Static vars may now be declared and initialized in assume-static
functions.
Passing too few
parameters in a dynamic function call is no longer allowed, as it allows the
function's caller to second-guess the
function's designer, reduces the ability to detect script bugs at
runtime, and may cause the application to crash if calling a built-in
function.
Revision 18 - February 21,
2009
Fixed: Incomplete bug-fix in previous revision causing concat
followed by assignment to skip the rest of the expression in some cases.
Revision 17 - February 20, 2009
Added: Menu icons via Icon
and NoIcon sub-commands of the Menu command.
Changed: Negative icon
numbers can now be used to indicate a resource ID within an executable.
Changed: Set default style
of menus to include MNS_CHECKORBMP.
Changed: Load both small and large versions of custom tray icons
to allow the correct icons to be shown in the appropriate places.
Fixed: Loading of icons from executable files at sizes other than
the system small/large.
Revision 16 - February 4,
2009
Fixed: Deleting a menu item partially deleted its associated
sub-menu.
Revision 15 - February 1, 2009
Fixed: SetFormat's presence in a *compiled* script was not
disabling binary number write-caching. SetFormat should now work
correctly in compiled scripts.
Revision 14 - February 1,
2009
Numerous bug-fixes and optimizations by Chris (pre-v1.0.48 beta).
Added: Support for regex callouts and the auto-callout option 'C'.
Changed: A_AhkVersion now
includes the revision number. For instance, this is 1.0.47.07.L14.
Fixed: HWND's/window ID's were sign-extended to 64-bit. For
instance, 0xb482057e became 0xffffffffb482057e.
Revision 13 - November 29, 2008
Fixed: Invalid DllCall
types were treated as INT in some build environments.
Added: Workaround for
GuiEscape issue when disabling focused control.
Changed version info: InternalName, ProductName and
FileDescription are now "AutoHotkey_L" instead of
"AutoHotkey".
Revision 12 - September 6, 2008
Fixed: Potential access violation when using property_get on a
built-in variable. -- DBGP
Revision 11 - September 5, 2008
Fixed: Remove checksum from AutoHotkeySC.bin via post-build script
(AutoHotkey must be installed).
Added: .L suffix to A_AhkVersion.
Added: Preliminary support
for DBGp (interactive debugging).
Revision 10 - August 2,
2008
Fixed: WheelLeft/WheelRight support, which was broken in revision
9.
Revision 9 - July 29, 2008
Fixed: Allow Break/Continue
in While.
Fixed: TrayTip in non-English Windows and possibly other
side-effects of using Vista headers.
Revision 8 - July 27, 2008
Added: #IfTimeout directive to set the timeout for evaluation of
#If expressions, in milliseconds. Default is 1000.
Added: Assume-static mode for functions. "Static" must
precede any local/global variable declarations.
Added: One-true-brace
support for While.
Changed: While now sets
A_Index to the iteration about to begin.
Revision 7 - July 26, 2008
Added: IsFunc(FuncName) - Returns a non-zero number if FuncName
exists in the script or as a built-in function.
Revision 5 - July 19, 2008
Cleaned up obsolete references to test scripts.
Added basic default test script.
Revision 4 - July 18, 2008
Added: #if (expression) -
Similar to #IfWinActive, but for arbitrary expressions.
Added: WheelLeft, WheelRight - Support for WM_MOUSEHWHEEL, which
was introduced with Windows Vista. (Requires Vista.) Added: While, expression - Loop while a condition is true.
Added: A_IsPaused - True if
the underlying thread is paused.
Added: A_IsCritical - True
if the current thread has been marked uninterruptible by the
"Critical" command.
Changed: Allow any number of parameters to be passed in dynamic
function calls. Fixed: Access Violation caused by
WinGetClass and subclassed windows.
Fixed: Access Violation
caused by empty dynamic function references.
Debugging Clients
Additional debugging features are supported via DBGp, a
common debugger protocol for languages and debugger UI communication.
See Interactive Debugging for more details. Some UIs or "clients" known to
be compatible with AutoHotkey are listed on this page:
SciTE4AutoHotkey
XDebugClient
Notepad++ DBGp Plugin
Script-based Clients
Command-line Client
Others
SciTE4AutoHotkey
SciTE4AutoHotkey is a
free, SciTE-based
AutoHotkey script editor. In addition to DBGp support, it provides syntax
highlighting,
calltips/parameter info and auto-complete for AutoHotkey, and
other useful editing features and scripting tools.
Debugging features include:
Breakpoints.
Run, Step Over/Into/Out.
View the call stack.
List name and contents of variables in local/global scope.
Hover over variable to show contents.
Inspect or edit variable contents.
View structure of objects.
http://fincs.ahk4.net/scite4ahk/
XDebugClient
XDebugClient is a simple open-source front-end DBGp client based on the .NET
Framework 2.0. XDebugClient was originally
designed for PHP with Xdebug, but a custom build compatible with
AutoHotkey is available below.
Changes:
Allow the
debugger engine to report a language other than "php".
Added AutoHotkey syntax highlighting.
Automatically listen for a connection from the debugger engine,
rather than waiting for the user to click Start
Listening.
Truncate property values at the first null-character, since
AutoHotkey currently returns the entire variable contents and
XDebugClient has no suitable interface for displaying binary
content.
Download: Binary; Source Code (also
see SharpDevelop, Dockpanel Suite and Advanced TreeView.)
Usage:
Launch
XDebugClient.
Launch AutoHotkey /Debug. XDebugClient should automatically open
the script file.
Click the left margin to set at least one breakpoint.
Choose Run from the Debug menu, or press F5.
When execution hits a breakpoint, use the Debug menu or shortcut
keys to step through or resume the script.
Features:
Syntax
highlighted, read-only view of the source code.
Breakpoints.
Run, Step Over/Into/Out.
View the call stack.
Inspect variables - select a variable name, right-click, Inspect.
Issues:
The user interface does not respond to user input while the script
is running.
No mechanisms are provided to list variables or set their values.
Notepad++ DBGp Plugin
A DBGp client is available
as a plugin for Notepad++. It is designed for PHP, but also works well with AutoHotkey.
Download: See DBGp plugin for Notepad++.
Usage:
Launch
Notepad++.
Configure the DBGp plugin via Plugins, DBGp, Config...
Note: File Mapping must
be configured. Most users will not be debugging remotely, and therefore may
simply put a checkmark
next to Bypass all mapping (local windows setup).
Show the debugger pane via the toolbar or Plugins, DBGp, Debugger.
Open the script file to be debugged.
Set at least one breakpoint.
Launch AutoHotkey /Debug.
Use the debugger toolbar or shortcut keys to control the debugger.
Features:
Syntax
highlighting, if configured by the user.
Breakpoints.
Run, Step Over/Into/Out, Run to cursor, Stop.
View local/global variables.
Watch user-specified variables.
View the call stack.
Hover over a variable to view its contents.
User-configurable shortcut keys - Settings, Shortcut Mapper...,
Plugin commands.
Issues:
Hovering over a single-letter variable name does not work - for
instance, hovering over a will attempt to retrieve a or a .
Hovering over text will attempt to retrieve a variable even if the
text contains invalid characters.
Notepad++ becomes unstable if property_get fails, which is
particularly problematic in light of the above. As a workaround,
AutoHotkey sends an empty property instead of an error code when a
non-existent or invalid variable is requested.
Script-based Clients
A script-based DBGp library
and example clients are available from GitHub.
dbgp_console.ahk: Simple command-line client.
dbgp_test.ahk: Demonstrates asynchronous debugging.
dbgp_listvars.ahk: Example client which justs lists the variables
of all running scripts.
GitHub: Lexikos /
dbgp
The DebugVars script provides a graphical user interface for
inspecting and changing the contents of variables and objects in any
running script (except compiled scripts). It also serves as a
demonstration of the dbgp.ahk library.
GitHub: Lexikos / DebugVars
Command-line Client
A command-line client is available from xdebug.org, however
this is not suitable for most users as it requires a decent understanding of
DBGp (the protocol).
Others
A number of other DBGp
clients are available, but have not been tested with AutoHotkey. For a list,
see Xdebug:
Documentation.
AutoHotkey_L New Features
This document describes features added in the AutoHotkey_L branch
of AutoHotkey development, now simply known as "AutoHotkey
1.1".
Caution: This document
has been neglected in recent years and may be missing some of the more recent
changes.
Control Flow
Break LoopLabelBreak out of a loop or any number of nested
loops.
Continue LoopLabelContinue a loop, even from within any number of
nested loops.
For x,y in z Loop through the contents of an object.
Loop Until Loop until a condition is true. Applicable to any type of Loop.
Try...Catch...FinallyProvides structured exception handling.
Throw Throws an exception.
Commands
FileEncoding Sets the default
encoding for FileRead, FileReadLine, Loop Read, FileAppend, and FileOpen.
See also:
Text Encodings
Gui See GUI Enhancements below.
IniRead/Write/Delete Read, write or delete entire sections, or retrieve a list of all
section names.
Menu, Icon Sets or removes a menu item's icon.
Run Improvements were made to the way parameters are parsed.
SendInput {U+nnnn} Sends a Unicode character. Unicode characters may be used directly
in Unicode builds.
SendLevel Controls which artificial keyboard and mouse events are ignored by
hotkeys and hotstrings.
SetFormat, IntegerFast, h|HSet lower-case or
upper-case hexadecimal format.
SetRegView, RegViewAllows registry
commands in a 32-bit script to access the 64-bit registry view and vice versa.
Transform, HTML Perform code page or HTML
transformations.
WinGet, ..., ProcessPathRetrieves the full path and name of the process
that owns a given window.
Directives
#If expressionSimilar to #IfWinActive, but for
arbitrary expressions.
#IfTimeout Sets the maximum time that may be spent evaluating a single #If expression.
#MenuMaskKeyChanges which key is used to mask
Win or Alt keyup events.
#Include <Lib>Includes a script file from a function library folder.
#InputLevelControls which artificial keyboard and mouse events are ignored by
hotkeys and hotstrings.
#Warn Enables or disables warnings for selected conditions that may be
indicative of developer errors.
Functions
ComObj... --
ComObjActive
ComObjEnwrap/Unwrap
ComObjParameter
ComObjType
FileOpen Provides object-oriented file I/O.
Func Retrieves a reference to a function.
GetKeyName/VK/SCRetrieves the name or text, virtual key code or scan code of a
key.
InStr Searches for a given occurrence of a string, from the left or the
right.
IsByRef Determines whether a ByRef parameter was supplied with a variable.
IsObject Determines whether a value is an object.
StrPut / StrGet Copies a string to or from a memory address, optional converting
it between code pages.
Trim Trims certain characters from the beginning and/or end of a
string.
RegEx (?CNum:Func)Calls a
function during evaluation of a regex pattern.
Function Libraries New "local library" and #Include
<LibName>.
Variadic Functions Functions may accept a
variable number of parameters via an array.
Static Initializers Static variables can now be initialized using any expression.
Objects
GeneralBehaviour and usage of objects in general.
ObjectAssociative arrays which can be extended with other functionality.
EnumeratorAllows items in a collection to be enumerated.
File Provides an interface to access a file. FileOpen returns
an object of this type.
Func Represents a user-defined or built-in function which can be called
by the script.
ComObjectSee ComObj
functions above.
Variables
A_Is64bitOSContains 1 (true) if the OS is 64-bit or
0 (false) if it is 32-bit.
A_IsUnicode In
Unicode builds, this variable contains 1 (true). In ANSI builds it is not defined, so is
effectively false. A_FileEncodingContains the default encoding for various
commands; see FileEncoding.
A_OSVersionSupports
Windows 7 and Windows 8; see A_OSVersion.
A_PriorKeyThe
name of the last key which was pressed prior to the most recent key-press or
key-release ... (More) A_PtrSize Contains
the size of a pointer, in bytes. This is either 4 (32-bit) or 8 (64-bit).
A_RegViewThe current
registry view as set by SetRegView.
A_ScriptHwndThe unique ID
(HWND/handle) of the script's hidden main window.
Datatypes
Ptr Equivalent to Int in
32-bit builds and Int64 in 64-bit
builds. Supported by DllCall, NumPut and NumGet.
AStr, WStrSupported only by DllCall; see Script Compatibility.
Unicode
CompatibilityHow to deal with Unicode in DllCall, etc.
Script FilesUsing Unicode in script files.
SendInputUsing Unicode with SendInput.
Other
ahk_exe Windows can be identified by the name or path of the process (EXE
file) which owns them.
Debugging Interactive debugging features (line by line execution etc.).
Error
HandlingTry/catch/throw
and increased usefulness for A_LastError.
GUI
EnhancementsVarious enhancements to the Gui command and related.
Icon Support Resource
identifiers and improved support for various icon sizes.
Other ChangesChanges affecting script compatibility.
Version HistoryHistory of AutoHotkey_L revisions.
Error Handling
Many commands support using try/catch instead of ErrorLevel for error handling. For example:
try
{
FileCopy, file1.txt,
C:\folder
FileDelete,
C:\folder\old.txt
}
catch
MsgBox An error occured!
Additionally, the following commands now set A_LastError to
assist with debugging: FileAppend, FileRead, FileReadLine, FileDelete,
FileCopy, FileMove, FileGetAttrib/Time/Size/Version,
FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete.
Function Libraries
In addition to the user library in %A_MyDocuments%\AutoHotkey\Lib and
standard library in the AutoHotkey directory, functions may be
auto-included from the "local library"
which resides in %A_ScriptDir%\Lib. For more information, see Libraries of Functions.
#Include <LibName> explicitly includes a library file which may be located in any
one of the function libraries.
GUI Enhancements
A number of enhancements
have been made to the Gui command
and related:
A name or HWND can be
used instead of a number between 1 and 99 when referring to a GUI.
Gui, New creates
a new anonymous GUI.
Any number of named or anonymous GUIs can be created.
New GUI options: +HwndOutputVar, +ParentGUI
A GUI's owner can be any arbitrary window: +Owner%HWND%.
Gui, Font can control anti-aliasing of text.
ActiveX controls such as
the Internet Explorer WebBrowser control are supported.
GuiControlGet, OutputVar,
Name gets the name of the variable associated with a
GUI control.
Keyboard accelerators such as Ctrl+O are supported automatically when used in Gui menus.
Font quality can be controlled by the Font sub-command.
Static Variables
Static variables can now be
initialized using any expression. For example:
Sleep 500
MsgBox % Time() "ms since the script started."
Time() {
static Tick := A_TickCount
return A_TickCount - Tick
}
Text Encodings
FileRead, FileReadLine, Loop Read and FileAppend support
the majority of Windows-supported text encodings, not just the system
default ANSI code page. FileEncoding can be
used to set the default encoding, which can be overridden for FileRead and
FileAppend as follows:
FileRead, OutputVar,
*Pnnn Filename
FileAppend , Text, Filename, Encoding
While nnn must be a numeric code page identifier, Encoding follows the
same format as FileEncoding.
See also: Script Compatibility
Variadic Functions and
Function-Calls
Variadic functions can
receive a variable number of parameters via an array, while variadic function-calls can be used to pass a variable
number of parameters to a function.
Improvements to Icon
Support
Unusual Sizes
Icon resources of any size supported by the operating system may
be extracted from executable files. When multiple sized icon resources
exist within an icon group, the most appropriate size
is used. Prior to revision 17, an
arbitrary icon resource was selected by the system,
scaled to the system large icon size, then scaled back to the
requested size.
Resource Identifiers
Negative icon numbers may be used to identify a group icon
resource within an executable file. For example, the following sets the tray
icon to the default icon used by ahk files:
Menu, Tray, Icon, %A_AhkPath%,
-160
Version 1.1.30.00
©2003-2014 Chris Mallett,
portions ©AutoIt
Team and the AHK community
Software License: GNU General Public License
Quick Reference
Getting started:
Text editors with AutoHotkey support
Frequently asked questions
Scripts:
Concepts and conventions: explanations of various things you need to know.
Scripting language: how to
write scripts.
Keyboard and mouse:
Hotkeys (mouse, joystick and keyboard shortcuts)
List of keys, mouse buttons and joystick controls
Other:
Script compatibility - AutoHotkey 1.0 users read this
Acknowledgements
A special thanks to
Jonathan Bennett, whose generosity in releasing AutoIt v2 as free software in 1999 served as an inspiration and
time-
saver for myself and many others worldwide. In
addition, many of AutoHotkey's enhancements to the AutoIt v2 command set, as
well as the Window Spy and the old script
compiler, were adapted directly from the AutoIt v3 source code. So thanks to
Jon and the other
AutoIt authors for those as
well.
Finally, AutoHotkey would not be what it is today without these other individuals.
~ Chris Mallett
Archived Changes
This document contains a history of changes made within the
original branch of AutoHotkey development, by Chris Mallett.
For newer changes, see Changes & New Features.
1.0.48.05
- September 25, 2009
Fixed crash of SendMessage and PostMessage when
wParam or lParam is omitted (broken by 1.0.48.04). [thanks Lexikos]
1.0.48.04 - September 25, 2009
Fixed StringSplit to work properly inside functions of compiled scripts (broken
by 1.0.35.01). [thanks engunneer & Lexikos]
Fixed SendPlay not to wait for the release of the Windows key prior to sending
an "L" keystroke (broken by 1.0.48.01). [thanks Lexikos]
Fixed A_EndChar to be valid when the B0 option
is present, and to be empty when there is no ending character (broken by 1.0.44.09).
[thanks Al2000]
Fixed FormatTime to yield
a valid time of day even when the specified month is out-of-range (broken by
1.0.48.00). [thanks
silveredge78]
Fixed FileCreateDir to
support a leading backslash even when it is the only backslash; e.g. \dir.
[thanks jaco0646]
Fixed GuiControl/GuiControlGet/Gui/SendMessage to work
reliably even when they trigger a callback or OnMessage function. [thanks Lexikos]
Fixed RegExMatch() not to
produce too few replacements when an empty-string match is followed by a
non-empty-string match.
Changed While() to be recognized as a loop rather than a function. [thanks Crash&Burn]
Improved UrlDownloadToFile to
support FTP and Gopher. [thanks Lexikos]
Improved the stdout/asterisk mode of FileAppend to write immediately rather than lazily to standard
output. [thanks Lexikos]
Added full support for if % expression. [thanks kenomby]
1.0.48.03
- May 3, 2009
Fixed ListLines On not to
erase the most recent log entry in the line history. [thanks Lexikos]
Fixed ListView to respond properly to mouse dragging when timers are
running. [thanks Solar]
Fixed key-up hotkeys so that
if one is created while its key is being held down, the release of the key
doesn't trigger the wrong hotkey.
[thanks Peter & engunneer]
1.0.48.02 - April 19, 2009
Changed and fixed Gosub and GroupActivate so that
when a function calls an external/public subroutine, that subroutine will treat all
dynamic variables as globals, and will have outside-of-function
GUI behavior. [thanks kenomby & Lexikos]
Improved performance of True/False/A_EventInfo in expressions by
treating them as integers vs. strings.
1.0.48.01 - April 15, 2009
Changed: For Windows Vista and later, hotkeys that include the Win key (e.g. #a) will wait for LWin and RWin to be
released before
sending any text containing an "L" keystroke. This
prevents such a hotkey from locking the PC. This behavior applies to all
sending
modes except SendPlay (which doesn't need it) and blind mode.
Fixed A_LoopFileExt to be blank for any filename having no extension but a period in
its pathname. [thanks Yek-Toho-Tua].
Fixed the assignment of
integers that are 19 or 20 characters long to work as they did prior to v1.0.48.
[thanks Laszlo & Lexikos]
Fixed function definitions to work properly inside a block. [thanks
rmarko]
Improved performance of A_Index in expressions by
treating it as an integer rather than a string.
Improved performance of if var [not] in/contains. [developed by Lexikos]
Improved ListLines with an
option to turn line-logging Off or On. [thanks kenomby & ruespe]
1.0.48 - February 25, 2009
Compatibility: The
change most likely to affect backward compatibility is that floating point
numbers stored in variables now have
higher precision. Scripts that rely on tiny differences in
precision would either need to be reviewed and updated, or have their
compatibility improved by using
SetFormat Float (e.g. SetFormat, Float, 0.6) anywhere in the
script. SetFormat Float disables
the higher precision, but gives up some of the new, faster
floating point performance.
Performance: The main theme of this release is faster performance.
Almost all scripts should run faster -- especially those that make
heavy use of expressions and
integer math/comparisons (which may run up to three times as fast). To achieve
the full benefit, a script
either should avoid using SetFormat or should use SetFormat's fast mode.
Performance improvements
Expressions and function calls are compiled more heavily, making them much faster (especially
complex integer expressions, including those with commas).
Binary numbers are cached for variables to avoid conversions
to/from strings. This makes numerical operations involving variables
much faster.
Literal integers in expressions and math/comparison commands are
replaced with binary integers, which makes them faster; e.g. X+5 and
if x > 5.
LOOPs, IFs, and ELSEs that have blocks (braces) are faster due to skipping the opening
'{'. A side-effect is that the '{' is omitted from
ListLines.
Thread-creation
performance is improved, which should help rapid-fire threads in OnMessage(), RegisterCallback(), and GUI events.
Changes that might affect existing scripts (other than
higher-precision floating point described at the top)
When SetFormat, Integer, Hex is in effect, assigning a literal decimal integer to a variable
also converts it to hex. Usually this is only a display issue.
For OnMessage()
performance, the message number and HWND arrive as standard numbers rather than
appearing unconditionally as
hex. Usually this is only a display issue.
To achieve various improvements in performance, scripts now use
slightly more memory (proportionate to the number of variables and
expressions).
Changed and fixed if var is time and
other uses of YYYYMMDDHHMISS date-time stamps to recognize that months outside
the
range 1-12 are invalid. [thanks Nick]
Changed and improved dynamic function calling to allow passing more parameters than defined by a function, in
which case the
parameters are evaluated but discarded. [developed by Lexikos]
Other improvements
Added function IsFunc(), which
indicates whether a function may be called dynamically.
[developed by Lexikos]
Added the while-loop, which repeats its commands until its expression evaluates to false. [developed by Lexikos]
Added an assume-static mode for
functions. [developed by Lexikos]
Added built-in variables A_IsPaused and A_IsCritical.
[developed by Lexikos]
Improved NumPut() to
support UInt64 like DllCall(). [thanks
Sean]
Improved mouse wheel support by adding WheelLeft and WheelRight as hotkeys and supporting them in Send, Click, and
related
commands. However, WheelLeft/Right has no effect on operating
systems older than Windows Vista. [developed by Lexikos]
Upgraded compiled script
compressor from UPX 3.00 to 3.03.
Fixes
Fixed inability to use MsgBox's timeout
parameter when the "Text" parameter had an expression containing
commas.
Fixed Menu, Delete, Item-that's-a-submenu not to disrupt the
associated submenu. [thanks animeaime & Lexikos]
Fixed the GUI Hotkey control to return usable hotkey names even for dead
keys (e.g. "^" instead of Zircumflex). [thanks DerRaphael]
Fixed RegDelete so that
it won't delete an entire root key when SubKey is blank. [thanks Icarus]
Fixed registry loops to
support subkey names longer than 259 (rare). In prior versions, such subkeys
would either be skipped or cause a
crash. [thanks Krzysztof Sliwinski & Eggi]
Fixed FileSelectFolder by providing an option to make
it compatible with BartPE/WinPE. [thanks markreflex]
Fixed window/control IDs (HWNDs), which in rare cases wrongly started with 0xFFFFFFFF instead of
just 0x. [thanks Micahs]
Fixed inability of Send commands to use the Down/Up modifiers with the "}" character.
[thanks neovars]
1.0.47.06
- March 9, 2008
Fixed crash when a function was called concurrently with an optional ByRef parameter omitted
by one thread but not
omitted by the
other. [thanks DeathByNukes]
Fixed Menu, Tray, MainWindow to enable the menu items in the main window's View menu. [thanks
Lexikos]
Added dynamic function calling. [developed by Lexikos]
1.0.47.05
- November 21, 2007
Fixed the Sort command: 1)
fixed the "function" option not to
misbehave when it's the last option in the list; 2) fixed the "unique" option
so that when the delimiter is CRLF, the last item can
be detected as a duplicate even when it doesn't end in CRLF; 3) fixed the
"unique" option not to append a
trailing delimiter when the last item is a duplicate. [thanks Roland]
Fixed RegExMatch() and RegExReplace() to yield
correct results even when Haystack and OutputVar are both the same variable.
[thanks Superfraggle]
Fixed inability to pass a parameter that is "a variable to
which ClipboardAll has been assigned". [thanks Joy2DWorld & Lexikos]
Updated RegEx/PCRE from 7.0 to 7.4. For a summary of the major
changes, see www.pcre.org/news.txt. For full details of every change and fix, see www.pcre.org/changelog.txt.
Added
GUI control "Tab2"
that fixes rare redrawing problems in the original "Tab" control
(e.g. activating a GUI window by clicking on a control's scrollbar). The original Tab control is
retained for backward compatibility because "Tab2" puts its tab
control after its
contained controls in the tab-key navigation order. [thanks
Xander]
1.0.47.04
- August 28, 2007
Fixed key-up hotkeys like a up:: not to block the pressing of the "a" key unless the
hotkey's #IfWin criteria are met. [thanks Roland]
Fixed Round(Var, NegativeNumber), which in rare cases was off by 1. [thanks Icarus]
Fixed crash of scripts that end in a syntax error consisting of an
orphaned IF-statement (broken by 1.0.47.00). [thanks msgbox of the
German forum]
Eliminated the "GetClipboardData" error dialog. Instead,
an empty string is retrieved when the data cannot be accessed within the
#ClipboardTimeout period.
[thanks ManaUser & Sean]
Changed GUI checkboxes and radio buttons to
default to "no word-wrap" when no width, height, or CR/LF characters are specified. This
solves display issues under certain unusual DPI
settings. [thanks Boskoop]
1.0.47.03
- August 1, 2007
Fixed expressions to allow
literal negative hexadecimal numbers that end in "E"; e.g. fn(-0xe).
[thanks Laszlo]
Fixed block syntax to allow
a function-call
immediately to the right of a '}'. [thanks Roland]
1.0.47.02
- July 19, 2007
Fixed the Number option of Edit controls to properly display a balloon tip when the user
types something other than a digit. [thanks
tfcahm]
Fixed WM_TIMER not to be
blocked unless it's posted to the script's main window. [thanks tfcahm]
Fixed wildcard hotkeys not to
acquire tilde behavior when the same hotkey exists in the script with a tilde. [thanks
Lexikos]
Fixed declaration initializers not to retain whitespace at the end of literal
numbers. Also, they now allow spaces between a closing quote
and the next comma. [thanks Hardeep]
1.0.47.01 - July 8, 2007
Fixed RunAs not to crash or misbehave when a domain is specified. [thanks
Markus Frohnmaier]
Changed relational operators to yield integers even when the inputs are floating point; e.g. 1.0
< 2.0 yields 1
vs. 1.0. [thanks Lexikos] 1.0.47 -
June 19, 2007
Added support for function libraries, which allow a script to call a function in an external file
without having to use #Include.
Added RegisterCallback(), which
creates a machine-code address that when called, redirects the call to a
function in the script.
[developed by Jonathan Rennison (JGR)]
Added NumGet() and NumPut(), which
retrieve/store binary numbers with much greater speed than
Extract/InsertInteger.
Improved Sort with an
option to do custom sorting according to the criteria in a callback function.
[thanks Laszlo]
Improved OnMessage() with an
option to allow more than one simultaneous thread. [thanks
JGR]
Improved Critical with an option to change the message-check interval, which may improve reliability for some usages.
[thanks
Majkinetor and JGR]
Changed Critical to put SetBatchLines -1 into effect.
Changed the error messages
produced by #ErrorStdOut to
contain a space before the colon. [thanks Toralf]
Fixed OnMessage() functions that return one of their own local variables to return the number
in that variable, not 0.
Fixed potential crashing of built-in variables that access the
registry (e.g. A_AppData, A_Desktop, A_MyDocuments, A_ProgramFiles).
[thanks Tekl]
1.0.46.17
- May 31, 2007
Fixed A_UserName (broken
by 1.0.46.16).
1.0.46.16 - May 30, 2007
Fixed Gui, Tab, TabName when
used after a previous Gui Tab. [thanks Toralf]
Improved SetTimer to treat negative periods as "run only once". [thanks Majkinetor]
Added GuiControlGet Hwnd, which is a more modular/dynamic way to retrieve a control's
HWND. [thanks Majkinetor]
Added built-in variables A_ThisLabel and A_ThisFunc, which
contain the names of the currently-executing label/function. [thanks Titan
& Majkinetor]
1.0.46.15
- May 9, 2007
Fixed GuiControl, GuiControlGet, and Gui ListView/TreeView to support static variables and ByRefs that
point to globals/statics.
[thanks Peter]
Fixed FileInstall causing
the Random command
to become non-random in compiled scripts. [thanks
Velocity]
Reduced the size of compiled scripts by about
16 KB due to UPX 3.0. [thanks to atnbueno for discovering the optimal
command-line
switches]
1.0.46.14
- May 2, 2007
Added the "require administrator" flag to the installer
to avoid a warning dialog on Windows Vista. [thanks Roussi Nikolov]
1.0.46.13 - May 1, 2007
Fixed hotkeys like *x
to fire even when x is also a hotkey
that is prevented from firing due to #IfWin. [thanks
Joy2DWorld &
Engunneer]
Improved optional parameters to accept quoted/literal strings as default
values.
Improved ByRef parameters with the ability to be optional (i.e. they may accept default values). [thanks Corrupt]
1.0.46.12 - April 24, 2007
Fixed inability to recognize a literal scientific notation number
that begins with 0, such as 0.15e+1. [thanks Laszlo]
1.0.46.11 - April 23, 2007
Fixed inability to have a function-call as the
first item in certain comma-separated expressions. [thanks
Majkinetor]
Fixed WinTitles like ahk_id
%ControlHwnd% in ControlGet's
FindString/Choice/List, and Control's
Add/Delete/Choose. [thanks
Freighter & PhiLho]
Improved floating
point support to recognize scientific notation; e.g. 1.2e-5 (the decimal point
is mandatory). Also improved "SetFormat
Float" with an option to output in scientific
notation. [thanks Laszlo]
1.0.46.10
- March 22, 2007
Fixed StringSplit inside assume-local functions so that
it creates a local array even when
OutputArray0 exists as a global but not a local. [thanks KZ]
Improved ListView's item-changed notification ("I") to indicate via ErrorLevel whether the item has been
selected/deselected,
focused/unfocused, and/or checked/unchecked. [thanks foom]
Added an additional layer of protection to compiled scripts. It is
recommended that scripts containing sensitive data or source code be
recompiled with the /NoDecompile switch.
1.0.46.09
- March 4, 2007
Fixed := deep
inside expressions when used to assign the result of a recursive function to a local variable (broken by 1.0.46.06). [thanks Laszlo]
Fixed inability to pass
certain ternary expressions to ByRef parameters. [thanks
Titan]
Fixed GuiControlGet,
OutputVar, Pos so that it doesn't make the OutputVar blank.
[thanks PhiLho]
Changed and fixed continuation sections so that the "Comment" option doesn't force the LTrim option into
effect. [thanks Titan]
Changed the Terminal Server Awareness flag back to "disabled" on AutoHotkey.exe and compiled
scripts. This improves flexibility and backward
compatibility (see discussion at forum).
1.0.46.08
- February 7, 2007
Fixed unreliability of ComSpec and environment variables on Windows 9x (broken by v1.0.46.07). [thanks Loriss]
Changed: When AutoHotkey.exe is launched without a script
specified, it will now run (or prompt you to create) the file
AutoHotkey.ahk in the My Documents folder.
The only exception is when AutoHotkey.ini exists in the working directory, in
which case it uses the old behavior of
executing that file.
Improved DllCall to support
an integer in place of the function name, which is interpreted as the address
of the function to call. [thanks Sean]
1.0.46.07
- January 23, 2007
Fixed crash of
illegally-named dynamic variables on the
left of an equal-sign assignment (broken by v1.0.45). [thanks PhiLho]
Fixed FileMoveDir's "Option 2" to work properly even when the directory
is being both renamed and moved. [thanks bugmenot]
Fixed inability to pass a variable ByRef if that
same expression changed it from empty to non-empty (when #NoEnv is absent). [thanks
Joy2DWorld]
Changed DllCall's A_LastError to
reflect only changes made by the script, not by AutoHotkey itself. [thanks
Azerty]
1.0.46.06 - January 16, 2007
Applied minor fixes and improvements to regular expressions by upgrading from PCRE 6.7 to 7.0. One of the most notable
improvements is the `a option, which recognizes any type of newline
(namely `r, `n, or `r`n). Similarly, the \R escape sequence means
"any single newline of
any type". See also: Full PCRE changelog
Changed and fixed all Control commands and StatusBarWait to obey SetTitleMatchMode RegEx as documented.
Changed RegExReplace() to
return the original/unaltered string rather than "" when an error
occurs.
Changed: Enabled the Terminal Server Awareness flag on AutoHotkey.exe and compiled scripts.
Improved performance when assigning large strings returned from user-defined functions. [thanks Laszlo]
1.0.46.05 - January 4, 2007
Fixed the Input command to allow
named end keys like {F9} to work even when the shift key is being held down
(broken by v1.0.45). [thanks Halweg]
Fixed inability of "Gui Show" to focus the GUI window when the tray menu is used both to
reload the script and to show the GUI
window. [thanks Rnon]
Fixed inability to pass some types of assignments (:=) to a ByRef
parameter. [thanks Laszlo]
1.0.46.04 - January 2, 2007
Fixed inability to pass the result of an assignment (:=) to a ByRef
parameter. [thanks Titan]
1.0.46.03 - December 18, 2006
Fixed ListView's floating point sorting to produce the correct ordering. [thanks
oldbrother/Goyyah/Laszlo]
1.0.46.02 - December 17, 2006
Fixed environment variables to work properly as input variables in various commands such as StringLen and StringReplace (broken
by
1.0.44.14). [thanks Camarade_Tux]
1.0.46.01
- December 15, 2006
NOTE: Although this release has been extensively tested, several
low-level enhancements were made. If you have any mission-critical
scripts, it is recommended that you retest them
and/or wait a few weeks for any bugs to get fixed.
Fixed comma-separated declaration initializers such as local
x = 1, y = 2 to work
even when immediately below an if/else/loop
statement.
Fixed comma-separated expressions so when
the leftmost item is an assignment, it will occur before the others rather than
after. [thanks Laszlo]
Changed and fixed function-calls so that any changes they make to dynamic variable names, environment variables, and built-in
variables (such as Clipboard) are always
visible to subsequent parts of the expression that called them.
Changed: When a multi-statement comma is followed immediately by a variable and an
equal sign, that equal sign is automatically
treated as a := assignment. For example, all of the following are assignments: x:=1,
y=2, a=b=c.
Changed comma-separated expressions to produce the following
effects: 1) the leftmost /= operator becomes
true divide rather
than
EnvDiv; 2)
blank values are not treated as zero in math expressions (thus they yield blank
results).
Improved the performance of
expressions by 5 to
20% (depending on type).
Improved the new assignment operators such as .= to support the Clipboard variable (even in comma-separated expressions).
Improved the .= operator so that it doesn't require a space to its left.
Improved GUI controls to
accept static variables as their associated variables (formerly only globals were allowed).
Added option HwndOutputVar to Gui Add, which stores a control's
HWND in OutputVar. [thanks Corrupt & Toralf]
1.0.46 - November 29, 2006
NOTE: Although this release has been extensively tested and is not
expected to break any existing scripts, several low-level
enhancements were made. If you have any mission-critical scripts,
it is recommended that you retest them and/or wait a few weeks for
any bugs to get fixed.
Added function SubStr(), which retrieves the
specified number of characters at the specified position in a string.
Added assignment operators //=, .=, |=, &=, ^=, >>=, and <<=, which
can be used anywhere in expressions. For example, Var .= "abc" appends
the string "abc" to Var's current contents.
Added full support in expressions for the operators :=, ++, --, +=, -=, *=, and /=
(formerly, they could be used only as the leftmost
operator on a line). All assignment operators (especially ++ and --) behave in a C-like way when their result is used by some other
operator.
Added the ternary operator (?:), which is a shorthand replacement for the if-else statement. For
example, var := x>y ? 2
: 3 assigns
the value 2 if x is greater than y; otherwise it assigns 3.
Added support for comma-separated expressions, which allow a single line
to contain multiple assignments, function calls, and other
expressions. [thanks PhiLho & Titan]
Improved variable declarations to support initialization on the same line.
Note: A static variable's
initialization occurs only once, before the script begins executing.
Improved line continuation to
support all expression operators. For example, a line that starts with
"?" or "+" is automatically appended
to the line above it.
Improved performance of
operators "." and ".=" to be as
fast as the percent-sign method of appending a string.
Improved expressions to
allow more types of consecutive unary operators such as !!Var. [thanks Laszlo]
Changed Critical to check
messages less often (20 vs. 10ms), which improves the reliability of
frequently-called OnMessage functions.
[thanks Majkinetor]
Changed: A variable named
simply "?" is no longer valid in expressions due to the new ternary operator.
Fixed hotkeys to
support ::: (colon as a hotkey) and : & x (colon
as a hotkey prefix).
Fixed the installer to remove psapi.dll from the AutoHotkey folder
(except on Windows NT4). This avoids a conflict with Internet
Explorer 7. [thanks to all who reported it]
1.0.45.04
- November 15, 2006
Fixed crash on Windows 9x
when a script doesn't actually run (e.g. due to syntax error) (broken by
v1.0.45). [thanks rogerg]
Changed Control Style|ExStyle to report ErrorLevel 0 vs. 1 when the requested style change
wasn't necessary because it was already in effect.
Improved #Include to
support %A_AppData% and %A_AppDataCommon%. [thanks Tekl]
1.0.45.03 - November 12, 2006
Fixed file-pattern loops not to
crash when recursing into paths longer than 259 characters. In addition, such
paths and files are now
ignored (skipped over) by file-pattern loops, FileSetAttrib, and FileSetTime. [thanks
PhilR]
Fixed functions that
call themselves and assign the result to one of their own locals (broken by v1.0.45). [thanks bjennings]
Fixed crash of scripts
containing regular expressions that have compile errors. [thanks PhiLho]
Fixed GuiControl not to
convert checkboxes into
3-state unless requested. [thanks JBensimon]
Changed UrlDownloadToFile to
announce a user-agent of "AutoHotkey" to the server rather than a
blank string. [thanks jaco0646]
Improved continuation sections to support semicolon comments inside the section via the
option-word Comments.
1.0.45.02
- November 8, 2006
Fixed StringUpper and StringLower to work
when OutputVar is the clipboard (broken by v1.0.45). [thanks songsoverruins]
Fixed the hotkeys ~Alt,
~Control, and ~Shift to fire upon press-down rather than release (broken by
v1.0.44).
Background: Without the tilde, Alt/Control/Shift fire upon release
to avoid taking over both the left and right key. But a specific left/right
hotkey like LAlt or RShift fires upon press-down.
1.0.45.01
- November 7, 2006
Fixed FileReadLine and FileSelectFile not to
crash or misbehave when other threads
interrupt them (broken by v1.0.45). [thanks toralf]
Fixed RegExMatch() so that when there's no
match, named subpatterns are properly set to "" in the output array.
[thanks PhiLho]
Fixed RegExMatch()'s "J" option to
properly write duplicate named subpatterns to the output array. [thanks PhiLho]
Changed SetWorkingDir and #Include DirName to succeed even for a root directory such as C: that lacks a
backslash.
Improved DllCall() to
display a warning dialog if the called function writes to a variable of zero
capacity.
1.0.45 - November 4, 2006
NOTE: Although this release has been extensively tested and is not
expected to break any existing scripts, several low-level performance
enhancements were made. If you have any
mission-critical scripts, it is recommended that you retest them and/or wait a
few weeks for
any bugs to get fixed.
Added support for regular expressions via RegExMatch(), RegExReplace(), and SetTitleMatchMode RegEx. [thanks Philip Hazel &
PhiLho]
Improved performance and
memory utilization of StringReplace.
Improved performance of the
:= operator for expressions and functions involving long strings.
Improved ControlClick with a
new option "NA" that avoids activating the target window (this mode
also improves reliability in some
cases). In addition, it's been documented that SetControlDelay -1 can improve the reliability of ControlClick in some cases.
[thanks
nnesori]
Changed GUI buttons to default to "no word-wrap" when no width, height, or CR/LF characters were specified. This
may solve button
display issues under some desktop themes.
Fixed "Transform HTML"
for the following characters: &`n><
Fixed misinterpretation of
lines starting with "if not is" such as "if not IsDone".
Fixed inability of "Gui Show" to move a window vertically downward to where its
bottommost row of pixels is now.
Fixed inability to use GroupActivate as the
only line beneath an IF or ELSE.
Fixed inability of the Input command to
differentiate between end-keys enclosed in braces and their (un)shifted
counterparts; e.g. '{' vs.
'['. [thanks Laszlo]
Older Changes
Visit www.autohotkey.com/changelog/ for even older changes.
Script Compatibility
Although many scripts written for AutoHotkey 1.0 do not require
changes to run on AutoHotkey 1.1, some may function incorrectly due
to necessary differences between the two versions. As
the most problematic differences only affect advanced functionality like
DllCall, most users do not need to be
concerned.
AutoHotkey 1.1 is also known as "AutoHotkey_L", while
AutoHotkey 1.0 was retrospectively labelled "AutoHotkey Basic". Some
older
versions of AutoHotkey_L used 1.0.* version numbers,
so for clarity, this document refers to the two branches of AutoHotkey by name
rather than version number.
Note: Some of the most
common problems are caused by changes required to support Unicode text, and can
be avoided by simply using the ANSI
version of AutoHotkey_L.
Table of Contents
Basic
High impact:
Certain syntax errors are no longer tolerated
FileRead may return corrupt binary data
Variable and function names do not allow [, ] or ?
DPI scaling is enabled by default for GUIs
Medium impact:
Transform's Unicode sub-command is unavailable on Unicode
versions
AutoHotkey.ahk is launched instead of AutoHotkey.ini
SetFormat, Integer, H
is case-sensitive
A_LastError is modified by more commands
MsgBox's handles commas more consistently
Gui +Owner overrides additional styles
SoundSet and SoundGet work better on Vista and later
~Tilde affects how custom modifier keys work
x
& y:: causes both x:: and x
up:: to fire when x is released
Low impact:
If var is type
ignores the system locale by default
GroupActivate sets ErrorLevel and GroupAdd's Label works differently
Run and RunWait interpret Target differently
Control-Z is not interpreted as end-of-file
Compatibility mode may cause confusion
A_IsCompiled is always read-only
Leading and trailing `t sequences are no longer discarded
Advanced
Unicode vs ANSI
VarSetCapacity
DllCall
NumPut / NumGet
Pointer Size
Basic
Syntax Errors
Certain syntax errors which were tolerated by AutoHotkey Basic are
not tolerated by AutoHotkey_L. Most
such errors can be easily
corrected once they are identified. The following errors are
detected immediately upon launching a script in AutoHotkey_L, and must be
corrected for the script to run:
A space, tab or comma is required between each command and its
parameters. For example, MsgBox<
foo and If!foo are not
tolerated.
Hotkey,
IfSomething, where
Something is invalid, is not tolerated.
Some other syntax errors are detected while the script is running.
These cause an error message to be displayed prior to exiting the
current thread:
Common: Unrecognized or
badly formatted Gui, Gui Show or GuiControl options.
GroupAdd with a blank group name.
Previously this caused the thread to silently exit.
Gui option +LastFoundExist must not be combined with another option, since that would cause
it to act the same as +LastFound.
Some other syntax errors
are currently not detected, but cause problems with AutoHotkey_L:
Auto-concat with ( is more
selective, so some invalid expressions like 12(34) no longer work.
FileRead
FileRead
translates text between code pages in certain common cases and therefore might
output corrupt binary data. To avoid
this, add the *c option or use FileOpen instead.
Variable and Function Names
The characters [, ] and ? are reserved for use in expressions, so are no longer valid in variable names. Consequently, ? (used in ternary
operations) no longer requires a space on either side. See also object syntax.
Errors may or may not be
detected automatically:
If a
script used these characters in variable names in expressions, generally the
script will run without displaying an error message,
but will misbehave as the characters will be interpreted as
operators rather than as part of a variable name.
If these characters are used in a double-deref (such as
Array%n% where n contains one of the above characters), an error message
is
displayed when the double-deref is evaluated, while the script is
running.
If these characters are used in other contexts, such as on the
left hand side of an assignment, in the name of a command's
input/output variable or between %percent% signs, an error message
is displayed and the script is prevented from launching.
DPI Scaling
DPI scaling is
enabled by default for script GUIs to ensure they scale according to the system DPI setting. If
enabled and the system DPI setting is
not 96 (100%), positions and sizes accepted by or returned from Gui commands
are not compatible with other commands. To
disable DPI scaling, use Gui -DPIScale.
Transform
Some Transform sub-commands are altered or unavailable in Unicode
versions of AutoHotkey_L:
Transform, Unicode is
unavailable. To assign Unicode text to the clipboard, use a regular assignment.
See also: StrPut/StrGet.
Transform, HTML supports
additional features.
Default Script
When AutoHotkey_L is launched without specifying a script, an .ahk
file is loaded by default instead of an .ini file. The name of this file
depends on the filename of the current executable. For more details, see Passing Command Line Parameters to a Script.
SetFormat, Integer[Fast], H
When an uppercase H is used, hexadecimal digits A-F will also be
in uppercase. AutoHotkey Basic always uses lowercase digits. See
SetFormat.
A_LastError
The following commands now set A_LastError to
assist with debugging: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy,
FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time,
FileCreateDir, RegRead, RegWrite, RegDelete.
Using any of these
commands causes the previous value of A_LastError to be
overwritten.
MsgBox
MsgBox's smart
comma handling has been changed to improve flexibility and consistency with all
other commands. In most cases,
MsgBox will just work as intended. In some rare cases, scripts relying on the old quirky behaviour
may observe a change in behaviour. For
instance:
; This is now interpreted as an expression (Options) followed by
text (Title)
; instead of as a single expression (Text) with multiple sub-expressions:
MsgBox % x, y
; Parentheses can be added to
force the old interpretation:
MsgBox % (x, y)
; This now shows an empty dialog instead of the text "0,
Title":
MsgBox 0, Title
; These behave as expected in both
AutoHotkey_L and AutoHotkey Basic:
MsgBox 0, Title, % ""
; Shows an empty dialog
MsgBox 0`, Title ;
Shows the text "0, Title"
; This now shows an empty dialog instead of the text ",
Title":
MsgBox,, Title
Gui +Owner
Applying the +Owner option
to a Gui also removes the WS_CHILD style and sets the WS_POPUP style. This may
break scripts which used +Owner to set
the parent window of a Gui after setting the styles.
Sound Commands on Windows
Vista and later
SoundSet, SoundGet, SoundSetWaveVolume and SoundGetWaveVolume have
improved support for Windows Vista and later. Typical changes in behaviour include:
Scripts affecting the whole system (as is usually intended)
instead of just the script itself.
Devices being numbered differently - each output or input is
considered a separate device.
~Tilde and Custom
Combination Hotkeys
As of [v1.1.14], the tilde prefix affects how a key works when used as a modifier key in a custom
combination.
Custom Combinations and Down/Up Hotkeys
Except when the tilde prefix is used, if both a key-down and a
key-up hotkey are defined for a custom modifier key, they will both fire
when the key is released. For
example, x & y:: causes both x:: and x up:: to fire when x is
released, where previously x:: never fired.
If var is type
If var is type ignores the system locale unless StringCaseSense, Locale has been used.
Window Groups
GroupActivate sets
ErrorLevel to 1 if no window was found to activate or 0 otherwise. Previously,
ErrorLevel was left unchanged.
GroupAdd's Label parameter
applies to the window group as a whole instead of to one particular window
specification within the group. A discussion
of this change can be found on the forums. However, using this parameter is not recommended; check
ErrorLevel after
calling GroupActivate instead.
Run / RunWait
AutoHotkey_L includes some enhancements to the way the Run and RunWait commands
interpret the Target parameter. This allows
some things that didn't work previously, but in some very rare
cases, may also affect scripts which were already working in AutoHotkey
Basic. The new behaviour is as follows:
If Target begins with a quotation mark, everything up to the next
quotation mark is considered the action, typically an executable
file.
Otherwise the first substring which ends at a space and is either
an existing file or ends in .exe, .bat, .com, .cmd or .hta is
considered the action. This allows file types such as .ahk, .vbs
or .lnk to accept parameters while still allowing "known"
executables such as wordpad.exe to be launched without an absolute
path as in previous versions.
Control-Z
Loop Read and FileReadLine no
longer interpret the character Control+Z (0x1A) as an end-of-file marker.
Any Control+Z, even
one
appearing at the very end of the file, is loaded as-is. FileRead already
ignored this character, so is not affected by this issue.
Compatibility Mode
If Compatibility mode is set
to Windows 95, 98/ME or NT4 in the properties of the EXE file used to run the
script, the script may not
behave correctly. This is because compatibility mode causes a
specific version of Windows to be reported to the application, but
AutoHotkey_L omits support for these versions. For example,
setting compatibility mode to Windows 95 or 98/ME will cause MsgBox
%A_OSVersion% to report WIN_NT4.
A_IsCompiled
A_IsCompiled is
defined as an empty string if the script has not been compiled. Previously it
was left undefined, which meant that
assignments such as A_IsCompiled := 1 were valid if the script hadn't been compiled. Now it is treated
as a read-only built-in variable in all
cases.
Escaped Whitespace
Escaped whitespace characters such as `t and ` are no longer trimmed from the beginning and end of each arg. For example,
StringReplace s, s, `t is now valid and will
remove all tab characters from s.
Unicode vs ANSI
A text value is often referred to as a string, as each text value is stored as a
sequence or string of characters. The numeric character code
and size (in bytes) of each character depends on
which version of AutoHotkey you are using: Unicode or ANSI. These details are
typically important for scripts which do any of the following:
Pass
strings to external functions via DllCall.
Pass strings via PostMessage/SendMessage.
Manipulate strings directly via NumPut/NumGet.
Use VarSetCapacity to
ensure a variable can hold a specific number of characters.
Scripts designed with one particular format in mind will often
encounter problems when run on the wrong version of AutoHotkey. For
instance, some scripts written for AutoHotkey Basic will function
correctly on the ANSI version of AutoHotkey_L but fail on Unicode
versions. If you aren't
sure which version you are using, run the following script:
MsgBox % A_IsUnicode ?
"Unicode" : "ANSI"
ANSI: Each character is one
byte (8 bits). Character codes above
127 depend on your system's language settings.
Unicode: Each character is two bytes (16 bits).
Character codes are as defined by the UTF-16 format.
Semantic note: Technically, some Unicode characters are
represented by two 16-bit code units, collectively known as a "surrogate
pair." Similarly, some ANSI code pages (commonly known as Double Byte Character Sets) contain some double-byte characters. However, for practical reasons these are almost always treated as two
individual units (referred to as "characters" for simplicity).
VarSetCapacity
VarSetCapacity sets the capacity of a var in bytes. To set a
variable's capacity based on the number of characters, the size of a character
must be taken into account. For example:
VarSetCapacity(ansi_var,
capacity_in_chars)
VarSetCapacity(unicode_var, capacity_in_chars * 2)
VarSetCapacity(native_var,
capacity_in_chars * (A_IsUnicode ? 2 : 1))
VarSetCapacity(native_var,
t_size(capacity_in_chars)) ; see below
There are two main uses for
VarSetCapacity:
1. Expand a variable to hold an estimated
number of characters, to enhance performance when building a string by means of
gradual
concatenation. For example, VarSetCapacity(var,
1000) allows for 1000 bytes, which is only 500 characters on Unicode
versions of AutoHotkey_L. This
could affect performance, but the script should still function correctly.
2. Resize a variable to hold a binary structure. If the structure
directly contains text, the format of that text must be taken into
account. This depends on the structure - sometimes ANSI text will
be used even in a Unicode version of AutoHotkey_L. If the
variable is too small, the
script may crash or otherwise behave unpredictably (depending on how the
structure is used).
DllCall
When the "Str" type is used, it means a string in the
native format of the current build. Since some functions may require or return
strings in a particular format, the following string types are
available:
Char Size C
/ Win32 Types Encoding
WStr16-bitwchar_t*, WCHAR*, LPWSTR, LPCWSTRUTF-16
AStr8-bitchar*, CHAR*, LPSTR, LPCSTR ANSI (the system default ANSI
code page)
Str -- TCHAR*, LPTSTR, LPCTSTR Equivalent to WStr
in Unicode builds and AStr in ANSI
builds.
If "Str" or the equivalent type for the current build is
used as a parameter, the address of the string or var is passed to the
function,
otherwise a temporary copy of the string is created in the desired
format and passed instead. As a general rule, "AStr" and
"WStr" should not be used
if the function writes a value into that parameter.
Note: "AStr" and "WStr" are equally valid for
parameters and the function's return value.
In general, if a script
calls a function via DllCall which accepts a string as a parameter, one of the
following approaches must be taken:
1. If both Unicode (W) and ANSI (A) versions of the function are
available, call the appropriate one for the current build. In the
following example, "DeleteFile" is internally known as
"DeleteFileA" or "DeleteFileW". Since
"DeleteFile" itself doesn't really
exist, DllCall automatically tries "A" or "W"
as appropriate for the current build:
DllCall("DeleteFile", "Ptr", &filename)
DllCall("DeleteFile", "Str", filename)
In this example, &filename passes the address of the
string exactly as-is, so the function must expect a string in the same format
as
the "Str" type. Note that "UInt" must be used
in place of "Ptr" in AutoHotkey Basic, but the resulting code may not
be 64-bit
compatible.
Note: If the function
cannot be found exactly as specified, AutoHotkey_L appends the "A" or
"W" suffix regardless of which DLL
is specified. However,
AutoHotkey Basic appends the "A" suffix only for functions in
User32.dll, Kernel32.dll, ComCtl32.dll, or
Gdi32.dll.
2. If the function only accepts a specific
type of string as input, the script may use the appropriate string type:
DllCall("DeleteFileA", "AStr", filename)
DllCall("DeleteFileW", "WStr", filename)
3. If the function must modify a string (in a non-native format),
the script must allocate a buffer as described above and pass its
address to the function. If
the parameter accepts input, the script must also convert the input string to
the appropriate format; this
can be done using StrPut.
NumPut / NumGet
When NumPut or NumGet are used with strings, the offset and type
must be correct for the given type of string. The following may be
used as a guide:
;
8-bit/ANSI strings: size_of_char=1 type_of_char="Char"
; 16-bit/UTF-16 strings:
size_of_char=2
type_of_char="UShort"
nth_char := NumGet(var, (n-1)*size_of_char,
type_of_char)
NumPut(nth_char, var, (n-1)*size_of_char,
type_of_char)
If var contains a string in the
native format, the appropriate values may be determined based on the value of A_IsUnicode:
nth_char := NumGet(var, t_size(n-1), t_char())
NumPut(nth_char, var, t_size(n-1), t_char())
; Define functions for convenience and clarity:
t_char() {
return A_IsUnicode ? "UShort" : "Char"
}
t_size(char_count=1) {
return A_IsUnicode ? char_count*2 : char_count
}
Pointer Size
Pointers are 4 bytes in 32-bit builds (including AutoHotkey Basic)
and 8 bytes in 64-bit builds. Scripts using structures or DllCalls may
need to account for this to run correctly on both
platforms. Specific areas which are affected include:
Offset calculation for fields in structures which contain one or
more pointers.
Size calculation for structures containing one or more pointers.
Type names used with DllCall, NumPut or NumGet.
For size and offset
calculations, use A_PtrSize. For
DllCall, NumPut and NumGet, use the Ptr type
where appropriate.
Remember that the offset of a field is usually the total size of
all fields preceding it. Also note that handles (including types like HWND
and HBITMAP) are essentially pointer-types.
/*
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess; // Ptr
HANDLE hThread;
DWORD dwProcessId; // UInt (4
bytes)
DWORD dwThreadId;
} PROCESS_INFORMATION,
*LPPROCESS_INFORMATION;
*/
VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt
DllCall("CreateProcess", <omitted for brevity>,
"Ptr", &pi, <omitted>)
hProcess := NumGet(pi,
0) ; Defaults to
"Ptr".
hThread := NumGet(pi, A_PtrSize) ;
dwProcessId := NumGet(pi,
A_PtrSize*2, "UInt")
dwProcessId := NumGet(pi,
A_PtrSize*2 + 4, "UInt")
Concepts and Conventions
This document covers some general concepts and conventions used by
AutoHotkey, with focus on explanation rather than code. The
reader is not assumed to have any prior knowledge of scripting or
programming, but should be prepared to learn new terminology.
For more specific details about syntax, see Scripting Language.
Table of Contents
Values
Strings
Numbers
Boolean
Nothing
Objects
Object Protocol
Variables
Uninitialised Variables
Built-in Variables
Environment Variables
Caching
Functions/Commands
Control Flow
Details
String Encoding
Pure Numbers
Names
Variable References vs Values
References to Objects
Values
A value is simply a piece of information within a program. For
example, the name of a key to send or a program to run, the number of
times a hotkey has been pressed, the title of a window to
activate, or whatever else has some meaning within the program or script.
AutoHotkey supports these
types of values:
Strings (text)
Numbers (integers and
floating-point numbers)
Objects
Some other related
concepts:
Boolean
Nothing
Strings
A string is simply text.
Each string is actually a sequence or string
of characters, but can be treated as a single entity. The length of a
string is the number of characters in the sequence, while the
position of a character in the string is merely that character's sequential
number. By convention in AutoHotkey, the first character is at
position 1.
A string of digits (or any other supported number format) is automatically
interpreted as a number when a math operation or comparison
requires it.
How literal text should be written within the script depends on
the context. For details, see Legacy Syntax and Strings (in expressions). For a more detailed explanation
of how strings work, see String Encoding.
Numbers
AutoHotkey supports these
number formats:
Decimal integers, such as 123, 00123 or -1.
Hexadecimal integers, such as 0x7B, 0x007B or -0x1.
Decimal floating-point numbers, such as 3.14159.
Hexadecimal numbers must
use the 0x or 0X prefix, except where noted in the documentation. This prefix must
be written after the + or -
sign, if present, and
before any leading zeroes. For example, 0x001 is valid, but 000x1 is not.
Numbers written with a
decimal point are always considered to be floating-point, even if the
fractional part is zero. For example, 42 and
42.0 are usually interchangeable, but not always. Scientific notation
is also recognized, but only if a decimal point is present (e.g. 1.0e4
and -2.1E-4).
The decimal separator is
always a dot, even if the user's regional settings specify a comma.
When a number is converted to a string, it is formatted according
to the current integer or float format. Although the SetFormat command
can be used to change the current format, it is
usually better to use the Format
function to format a string. Floating-point numbers can
also be formatted by using
the Round
function.
For details about the range and accuracy of numeric values, see Pure Numbers.
Boolean
A boolean value can be either true
or false. Boolean values are used to
represent anything that has exactly two possible states, such as the
truth of an expression. For example, the expression (x <= y) is true when x has lesser or equal value to y. A boolean value
could also
represent yes or no, on or off, down or up
(such as for GetKeyState) and so
on.
AutoHotkey does not have a specific boolean type, so it uses the
integer value 0 to represent false and 1 to represent true. When a
value
is required to be either true or false, a blank or
zero value is considered false and all other values are considered true.
(Objects are always considered true.)
The words true and false are built-in variables containing 1 and 0. They
can be used to make a script more readable.
Nothing
AutoHotkey does not have a value which uniquely represents nothing, null, nil or undefined, as seen in other languages.
Instead, an
empty string (a string of zero length) often has this meaning.
If a variable or parameter is said to be "empty" or
"blank", that usually means an empty string (a string of zero
length).
Objects
There are generally two
ways of viewing objects:
An object
contains a group of values, allowing the group itself to be treated as one
value. For example, an object could contain an
array or sequence of items, or a set of related values, such as
the X and Y coordinates of a position on the screen. Objects can be
used to build complex structures by combining them with other
objects.
An object can represent a thing, a service, or something else, and can provide ways for the script to
interact with this thing or
service. For example, a BankAccount object might have properties such as the account number,
current balance and the owner of
the account, and methods to withdraw or deposit an amount.
The proper use of objects (and in particular, classes) can
result in code which is modular and
reusable. Modular code is usually easier to test, understand and maintain. For instance, one can
improve or modify one section of code without having to know the details of
other
sections, and without having to make corresponding changes to
those sections. Reusable code saves time, by avoiding the need to write
and test code for the same or similar tasks over and over.
When you assign an object to a
variable, as in myObj
:= {}, what you store is not the object itself, but a reference to the
object. Copying that variable, as in yourObj := myObj, creates a new reference to the
same object. A change such as myObj.ans
:= 42 would be
reflected by both myObj.ans and yourObj.ans, since they both refer to the same object. However, myObj
:= Object() only affects the variable myObj,
not the variable yourObj, which still refers to the original
object.
Object Protocol
This section builds on
these concepts which are covered in later sections: variables, functions
Objects work through the
principle of message passing. You don't know where an object's code or
variables actually reside, so you must pass a
message to the object, like "give me foo" or "go do bar", and rely on the object to respond
to the message. Objects in AutoHotkey support
the following basic messages:
Get a
value.
Set a value, denoted by
:=.
Call a method, denoted
by ().
Each message can optionally have one or more parameters (and, for Set, the
value). Usually there is at least one parameter, and it is
interpreted as the name of a property or method, a key or an array
index, depending on the object and how you're using it. The
parameters of a message are specified using three different
patterns: .Name, [Parameters] and (Parameters), where Name is a
literal
name or identifier, and Parameters is a list
of parameters (as sub-expressions), which can be empty/blank ([] or ()).
For Get and Set, .Name and [Parameters] can be
used interchangeably, or in combination:
myObj[arg1, arg2, ..., argN]
myObj.name
myObj.name[arg2, ..., argN]
For Call, .Name and [Parameter] can be used
interchangeably, and must always be followed by (Parameters):
myObj.name(arg2, ..., argN)
myObj[arg1](arg2, ..., argN)
Notice that if name is present, it becomes the first parameter. myObj.name is equivalent to myObj["name"], while myObj.123 is
equivalent to myObj[123]. This is
true for every type of object, so it is always possible to compute the name of
a property or method at
runtime, rather than hard-coding it into the script.
Although name or arg1 is considered to be the first
parameter, remember that these are just messages, and the object is free to handle
them in any way. In a method call such as those shown above,
usually the object uses name or arg1 to identify which method should be
called, and then only arg2 and beyond are passed to the method. In effect, arg2
becomes the method's first apparent parameter.
Generally, Set has the same meaning as an assignment,
so it uses the same operator:
myObj[arg1, arg2, ..., argN] := value
myObj.name := value
myObj.name[arg2, ..., argN] :=
value
Currently there is also a
"hybrid" syntax allowed with Set,
but it is best not to use it:
myObj.name(arg2, ..., argN) :=
value
Technically, value is passed as the last the parameter of the Set message; however,
this detail is almost never relevant to script authors. Generally one can simply think of it as "the value
being assigned".
Variables
A variable allows you to use a name as a placeholder for a value.
Which value that is could change repeatedly during the time your script
is running. For example, a hotkey could use a
variable press_count to count the number of
times it is pressed, and send a different key whenever press_count is a multiple of 3 (every third press). Even a variable which is
only assigned a value once can be useful. For
example, a WebBrowserTitle variable could be used to make your code easier to update when
and if you were to change your preferred web browser, or if the title or window class changes due to a software update.
In AutoHotkey, variables are created simply by using them. Each
variable is not permanently
restricted to a single data type, but can
instead hold a value of any type: string, number or object. Each
variable starts off empty/blank; in other words, each newly created
variable contains an empty string until it is assigned some other
value.
A variable has three main
aspects:
The variable's name.
The variable itself.
The variable's value.
Certain restrictions apply to variable names - see Names for
details. In short, it is safest to stick to names consisting of ASCII letters
(which are case insensitive), digits and underscore, and to avoid
using names that start with a digit.
A variable name has scope,
which defines where in the code that name can be used to refer to that
particular variable; in other words,
where the variable is visible. If a variable is not visible within
a given scope, the same name can refer to a different variable. Both
variables might exist at the same time, but only one is visible to
each part of the script. Global variables are
visible in the "global scope" (that is, outside of functions), but must usually be declared
to make them visible inside a function. Local variables are visible only inside the
function which created them.
A variable can be thought of as a container or storage location
for a value, so you'll often find the documentation refers to a variable's
value as the contents of the variable. For a variable x := 42, we can
also say that the variable x has the number 42 as its value, or that
the value of x is 42.
It is important to note
that a variable and its value are not the same thing. For instance, we might
say "myArray is an array", but what we
really mean is that myArray is a variable containing
a reference to an array. We're taking a shortcut by using the name of the
variable to refer to its value, but
"myArray" is really just the name of the variable; the array object
doesn't know that it has a name, and could be
referred to by many different variables (and therefore many
names).
Uninitialised Variables
To initialise a variable is
to assign it a starting value. Although the program automatically initialises
all variables (an empty string being the default
value), it is good practice for a script to always initialise its variables
before use. That way, anyone reading the script can see
what variables the script
will be using and what starting values they are expected to have.
It is usually necessary for the script to initialise any variable
which is expected to hold a number. For example, x := x + 1 will not
work if x has never been assigned a value, since the empty string is considered to be non-numeric. The
script should have assigned a
starting value, such as x := 0. There are some cases where empty values are assumed to be 0, but it is best not to
rely on this.
Script authors can use the #Warn
directive to help find instances where a variable is used without having been
initialised by the script.
Built-in Variables
A number of useful variables are built into the program and can be
referenced by any script. With the exception of Clipboard,
ErrorLevel, and command line parameters, these variables are read-only; that is, their contents cannot be
directly altered by the script.
By convention, most of these variables start with the prefix A_, so it
is best to avoid using this prefix for your own variables.
Some variables such as A_KeyDelay and A_TitleMatchMode
represent settings that control the script's behavior, and retain separate
values for each thread. This
allows subroutines launched by new threads (such as for hotkeys, menus, timers
and such) to change settings without
affecting other threads.
Some special variables are not updated periodically, but rather
their value is retrieved or calculated whenever the script references the
variable. For example, Clipboard
retrieves the current contents of the clipboard as text, and A_TimeSinceThisHotkey calculates the
number of milliseconds that have elapsed since the hotkey was
pressed.
Related: list of built-in variables.
Environment Variables
Environment variables are maintained by the operating system. You
can see a list of them at the command prompt by typing SET then
pressing Enter.
A script may create a new environment variable or change the
contents of an existing one with EnvSet. Such
additions and changes are
not seen by the rest of the system. However, any programs or
scripts which the script launches by calling
Run or RunWait usually
inherit a copy of the parent script's
environment variables.
It is recommended that all
new scripts retrieve environment variables such as Path via EnvGet:
EnvGet, OutputVar, Path ; For explanation, see #NoEnv.
If a script lacks the #NoEnv directive, reading an empty variable will instead return the
value of the environment variable with that
name, if there is one. This can cause confusion, so it is
recommended that all new scripts use #NoEnv.
Caching
Although a variable is typically thought of as holding a single
value, and that value having a distinct type (string, number or object),
AutoHotkey automatically converts between numbers and strings in
cases like myString + 1 and MsgBox %myNumber%. As
these
conversions can happen very frequently, whenever a variable is
converted, the result is cached in
the variable.
In effect, a variable can contain both a string and a number
simultaneously. Usually this just improves the script's performance with no
down-sides, but if a variable contains both a number and a string,
is it number, or is it a string? This ambiguity causes unexpected
behavior in at least two cases:
1. COM objects. In order to pass parameters to a COM object, the
program must convert the variable's content to either a number or
a
string. Some COM objects throw an exception if the wrong type of
value is passed. If a variable has both, the number is used.
Usually this gets the right result, but sometimes it doesn't.
2. Objects don't have
the capability to store both a number and a string as a key or value. Since
numbers are more memory-efficient,
if a variable has both, the number is used (except for
floating-point values used as keys).
SetFormat's slow
mode forces the assignment of a pure number to immediately convert that number
to a string. For integers, the number
is also stored, so this doesn't have adverse effects other than to
performance. For floats, the number is not stored, since SetFormat affects
the precision of the value, possibly even truncating
all decimal places. In other words, SetFormat's slow mode prevents pure floats
from being stored in variables.
Taking the address of a variable effectively converts the
variable's value to a string, disabling caching until the variable's address
changes (this happens when its capacity
changes). This is both for backward-compatibility and because the script could
change the value
indirectly via its address at any time, making the cache
inaccurate.
Related
Variables: basic usage and examples.
Variable Capacity and Memory: details about limitations.
Functions/Commands
A function or command
is the basic means by which a script does something.
In essence, functions and commands are the same thing, so the
concepts explained here apply to both. However, the long history of
AutoHotkey v1 and an emphasis on backward-compatibility have
resulted in a divide between commands,
which require legacy syntax, and
functions, which require expression syntax.
Commands and functions can have many different purposes. Some
functions might do no more than perform a simple calculation, while
others have immediately visible effects, such as
moving a window. One of AutoHotkey's strengths is the ease with which scripts
can
automate other programs and perform many other common tasks by
simply calling a few functions. See the command and function list
for examples.
Throughout this documentation, some common words are used in ways
that might not be obvious to someone without prior experience.
Below are several such words/phrases which are used
frequently in relation to functions and commands:
Call a function or command
Calling a
function or command causes the program to invoke, execute or evaluate it. In
other words, a function call temporarily
transfers control from the script to the function. When the
function has completed its purpose, it returns
control to the script. In
other words, any code following the function call does not execute
until after the function completes.
However, sometimes a function or command completes before its
effects can be seen by the user. For example, the Send command
sends keystrokes, but may return before the keystrokes reach their
destination and cause their intended effect.
Parameters
Usually a
command or function accepts parameters
which tell it how to operate or what to operate on. Each parameter is a value,
such as a string or number. For example, WinMove moves a
window, so its parameters tell it which window to move and where to
move it to. Parameters can also be called arguments. Common
abbreviations include param and arg.
Pass parameters
Parameters
are passed to a function or command, meaning that a value is specified for each
parameter of the function or command
when it is called. For
example, one can pass the name of a
key to GetKeyState to
determine whether that key is being held down.
Return a value
Functions return a value, so the result of the function is often
called a return value. For example, StrLen returns
the number of
characters in a string. Commands do not return a result directly;
instead, they store the result in a variable.
Functions may also do
this, such as when there is more than one result.
Functions and commands usually expect parameters to be written in
a specific order, so the meaning of each parameter value depends on
its position in the comma-delimited list of
parameters. Some parameters can be omitted, in which case the parameter can be
left blank,
but the comma following it can only be omitted if all remaining
parameters are also omitted. For example, the syntax for ControlSend is:
ControlSend , Control, Keys,
WinTitle, WinText, ExcludeTitle, ExcludeText
Square brackets signify that the enclosed parameters are optional
(the brackets themselves should not appear in the actual code).
However, ControlSend isn't useful unless Keys are specified, and usually one must also specify the
target window. For example:
ControlSend, Edit1, ^{Home}, A
; Correct. Control is specified.
ControlSend, ^{Home}, A
; Incorrect: Parameters are mismatched.
ControlSend,, ^{Home}, A ; Correct. Control is omitted.
Methods
Methods are functions which operate on a particular object. While there can only be
one function named Send (for example), there can
be
as many methods named Send as there are objects, as
each object (or class of objects) can respond in a different way. For this
reason, the target object (which may be a
variable or sub-expression) is specified to left of the method name instead of
inside the parameter list. For details, see Object Protocol.
Control Flow
Control flow is the order in which individual statements are
executed. Normally statements are executed sequentially from top to bottom,
but a control flow statement can override this, such
as by specifying that statements should be executed repeatedly, or only if a
certain
condition is met.
Statement
A
statement is simply the smallest
standalone element of the language that expresses some action to be carried
out. In AutoHotkey,
statements include commands, assignments, function calls and other
expressions. However, directives, labels (including hotkeys
and hotstrings), and declarations without assignments are not
statements; they are processed when the program first starts up,
before the script executes.
Execute
Carry
out, perform, evaluate, put into effect, etc.
Execute basically has the same meaning as in non-programming speak.
Body
The body of a
control flow statement is the statement or group of statements to which it
applies. For example, the body of an if
statement is executed only
if a specific condition is met.
For example, consider this
simple set of instructions:
1. Open Notepad
2. Wait for Notepad to
appear on the screen
3. Type "Hello,
world!"
We take one step at a time, and when that step is finished, we
move on to the next step. In the same way, control in a program or script
usually flows from one statement to the next statement. But what
if we want to type into an existing Notepad window? Consider this
revised set of instructions:
1. If Notepad is not running:
1. Open Notepad
2. Wait for Notepad to appear on the screen
2. Otherwise:
1. Activate Notepad
3. Type "Hello,
world!"
So we either open Notepad or activate Notepad depending on whether
it is already running. #1 is a conditional statement, also known as
an if statement; that is, we execute its body (#1.1 -
#1.2) only if a condition is met. #2 is an else
statement; we execute its body (#2.1)
only if the condition of a previous if statement (#1) is not met.
Depending on the condition, control flows one of two ways: #1 (if true) →
#1.1 → #1.2 → #3; or #1 (if false)
→ #2 (else) → #2.1 → #3.
The instructions above can
be translated into the code below:
if (not WinExist("ahk_class
Notepad"))
{
Run Notepad
WinWait ahk_class Notepad
}
else
WinActivate ahk_class
Notepad
Send Hello`, world!
In our written instructions, we used indentation and numbering to
group the statements. Scripts work a little differently. Although
indentation makes code easier to read, in AutoHotkey it does not
affect the grouping of statements. Instead, statements are grouped by
enclosing them in braces, as shown above. This is called a block.
For details about syntax - that is, how to write or recognise
control flow statements in AutoHotkey - see Control Flow.
Details
String Encoding
Each character in the string is represented by a number, called
its ordinal number, or character code. For example, the value "Abc"
would be represented as follows:
A b c
659899
The encoding of a string is the way in which numbers are mapped to
symbols. There are many different encodings, but as all of those
supported by AutoHotkey include ASCII as a subset, character codes
0 to 127 always have the same meaning. For example, 'A' always
has the character code 65.
Although AutoHotkey provides ways to work with text in various
encodings, the built-in commands and functions--and to some degree
the language itself--all assume string values to be
in one particular encoding. This is referred to as the native encoding. The
native
encoding depends on the version of AutoHotkey:
Unicode versions of AutoHotkey use UTF-16. The smallest element in
a UTF-16 string is two bytes (16 bits). Unicode characters
in the range 0 to 65535 (U+FFFF) are represented by a single
16-bit code unit of the same value, while characters in the range
65536 (U+10000) to 1114111 (U+10FFFF) are represented by a
surrogate pair; that is, exactly two 16-bit code units between
0xD800 and 0xDFFF. (For further explanation of surrogate pairs and
methods of encoding or decoding them, search the Internet.)
ANSI versions of AutoHotkey use the system default ANSI code page,
which depends on the system locale or "language for non-
Unicode programs" system setting. The smallest element of an
ANSI string is one byte. However, some code pages contain
characters which are represented by sequences of multiple bytes (these
are always non-ASCII characters).
Generally, other parts of
this documentation use the term "character" to mean a string's
smallest unit; bytes for ANSI strings and 16-bit code units for Unicode strings. For practical reasons, the
length of a string and positions within a string are measured by counting these
fixed-size units, even though they may not be
complete Unicode characters.
FileRead, FileAppend, FileOpen and the File object provide
ways of reading and writing text in files with a specific encoding.
The functions StrGet and StrPut can be
used to convert strings between the native encoding and some other specified
encoding.
However, these are usually only useful in combination with data
structures and the DllCall
function. Strings which are passed directly to or from DllCall
can be converted to ANSI or UTF-16 by using the AStr or WStr parameter types.
Techniques for dealing with the differences between ANSI and
Unicode versions of AutoHotkey can be found under Unicode vs ANSI.
Pure Numbers
A pure or binary number is one which is stored in
memory in a format that the computer's CPU can directly work with, such as to
perform math. In most cases, AutoHotkey automatically converts
between numeric strings and pure numbers as needed, and rarely
differentiates between the two types. AutoHotkey primarily uses
two data types for pure numbers:
64-bit
signed integers (int64).
64-bit binary floating-point numbers (the double or binary64 format of the IEEE 754
international standard).
In other words, scripts are
affected by the following limitations:
Integers must be within the range -9223372036854775808
(-0x8000000000000000, or -263) to 9223372036854775807
(0x7FFFFFFFFFFFFFFF, or 263-1). Although larger values can be contained within a string, any
attempt to convert the string to a
number (such as by using it in a math operation) might yield
inconsistent results.
Floating-point numbers generally support 15 digits of precision.
However, converting a floating-point number to a string causes
the number to be rounded according to the current float format, which
defaults to 6 decimal places. If the "slow" mode of
SetFormat is
present anywhere in the script, numbers are always converted to strings when assigned to a variable.
Note: There are some
decimal fractions which the binary floating-point format cannot precisely
represent, so a number is rounded to the closest representable number. This may lead to unexpected
results. For example:
SetFormat FloatFast, 0.17 ;
Show "over-full" precision
MsgBox % 0.1 + 0 ;
0.10000000000000001
MsgBox % 0.1 + 0.2 ; 0.30000000000000004
MsgBox % 0.3 + 0 ; 0.29999999999999999
MsgBox % 0.1 + 0.2 = 0.3 ; 0 (not equal)
One strategy for dealing
with this is to avoid direct comparison, instead comparing the difference. For
example:
MsgBox % Abs((0.1 + 0.2) - (0.3))
< 0.0000000000000001
Another strategy is to always convert to string (thereby applying
rounding) before comparison. There are generally two ways to do this
while specifying the precision, and both are shown
below:
MsgBox % Round(0.1 + 0.2, 15) = Format("{:.15f}", 0.3)
Names
AutoHotkey uses the same set of rules for naming various things,
including variables, functions, window groups, GUIs, classes
and
methods:
Case sensitivity: None for ASCII characters. For example, CurrentDate is the same as currentdate.
However, uppercase non-
ASCII characters such as 'Ä' are not considered equal to their lowercase counterparts, regardless of
the current user's locale. This
helps the script to behave consistently across multiple locales.
Maximum length: 253 characters.
Allowed characters: Letters, numbers, non-ASCII characters, and
the following symbols: _ # @ $
Due to style conventions, it is generally better to name your
variables using only letters, numbers, and the underscore character (for
example: CursorPosition, Total_Items, and entry_is_valid).
This style allows people familiar with other computer languages to
understand your scripts more easily.
Although a variable name may
consist entirely of digits, this is generally used only for incoming command line parameters. Such
numeric names cannot be used in expressions because they would be
seen as numbers rather than variables. It is best to avoid starting a
name with a digit, as such names are confusing and will be
considered invalid in AutoHotkey v2.
As the following characters may be reserved for other purposes in
AutoHotkey v2, it is recommended to avoid using them: # @ $
Property names in classes have the same rules and restrictions as
variable names, except that the three characters listed above (# @ $) are
not allowed. Although they can be used in a method
definition, calling such a method requires using square brackets. For example,
myObject.@home() is not valid, but myObject["@home"]() is acceptable.
Variable References vs
Values
Variables have certain attributes that blur the line between a
variable and its value, but it is important to make the distinction. In
particular, consider objects and ByRef parameters.
Although we may say the variable myArray contains an array (which is a type of object), what the variable
contains isn't the array itself
but rather a reference or pointer
to the array. Any number of variables can contain a reference to the same
object. It may be helpful to
think of a variable as just a name in that case. For instance,
giving a person a nickname doesn't cause a clone of that person to come into
existence.
By default, variables are passed to user-defined functions by
value. In other words, the value contained by the variable is copied into the
variable which corresponds to the function's
parameter. ByRef parameters allow you to pass a variable by reference, or in other words, to make one parameter of the function an alias for your
variable, allowing the function to assign a new value to your variable.
Because a variable only ever contains a reference to an
object and not the object itself, when you pass such a variable to a non-ByRef
parameter, what the function receives is a reference to the same
object. This allows the function to modify the object, but it does not
allow the function to modify the variable which the function's caller used, because the function only has
a reference to the object, not the variable.
References to Objects
Scripts interact with an object only indirectly, through a reference
to the object. When you create an object, the object is created at some
location you don't control, and you're given a
reference. Passing this reference to a function or storing it in a variable or
another object
creates a new reference to the same object. You release a
reference by simply using an assignment to replace it with any other value. An
object is deleted only after all references have been
released; you cannot delete an object explicitly, and should not try.
ref1 := Object() ;
Create an object and store first reference
ref2 := ref1 ; Create a new reference to the same
object
ref1 := "" ; Release the first reference
ref2 := "" ; Release the second reference; object
is deleted
If that's difficult to understand, try thinking of an object as a
rental unit. When you rent a unit, you're given a key which you can use to
access the unit. You can get more keys and use them to access the
same unit, but when you're finished with the unit, you must hand all
keys back to the rental agent. Usually a unit wouldn't be deleted,
but maybe the agent will have any junk you left behind removed; just as
any values you stored in an
object are freed when the object is deleted.
Frequently Asked Questions
(FAQ)
Table of Contents
Language Syntax
When are quotation marks used with commands and their
parameters?
When exactly are variable names enclosed in percent signs?
When should percent signs and commas be escaped?
General Troubleshooting
What can I do if AutoHotkey won't install?
Why do some lines in my script never execute?
Why doesn't my script work on Windows xxx even though it worked on a previous version?
How do I work around problems caused by User Account Control
(UAC)?
I can't edit my script via tray icon because it won't start due
to an error. Can I find my script somewhere else?
How can I find and fix errors in my code?
Why is the Run command unable to launch my game or program?
Why are the non-ASCII characters in my script displaying or
sending incorrectly?
Why don't Hotstrings, Send, and MouseClick work in certain
games?
How can performance be improved for games or at other times when
the CPU is under heavy load?
My antivirus program flagged AHK as malware. Does it really
contain a virus?
Common Tasks
Where can I find the official build, or older releases?
Can I run AHK from a USB drive?
How can the output of a command line operation be retrieved?
How can a script close, pause, or suspend other script(s)?
How can a repeating action be stopped without exiting the
script?
How can context sensitive help for AutoHotkey commands be used
in any editor?
How to detect when a web page is finished loading?
How can dates and times be compared or manipulated?
How can I send the current Date and/or Time?
How can I send text to a window which isn't active or isn't
visible?
How can Winamp be controlled even when it isn't active?
How can MsgBox's button names be changed?
How can I change the default editor, which is accessible via
context menu or tray icon?
How can I save the contents of my GUI associated variables?
Can I draw something with AHK?
How can I start an action when a window appears, closes or
becomes [in]active?
Hotkeys, Hotstrings, and
Remapping
How do I put my hotkeys and hotstrings into effect automatically
every time I start my PC?
I'm having trouble getting my mouse buttons working as hotkeys.
Any advice?
How can tab and space be defined as hotkeys?
How can keys or mouse buttons be remapped so that they become
different keys?
How do I detect the double press of a key or button?
How can a hotkey or hotstring be made exclusive to certain
program(s)? In other words, I want a certain key to act as it normally
does except when a specific window is active.
How can a prefix key be made to perform its native function
rather than doing nothing?
How can the built-in Windows shortcut keys, such as Win+U (Utility
Manager) and Win+R (Run), be changed or disabled?
Can I use wildcards or regular expressions in Hotstrings?
How can I use a hotkey that is not in my keyboard layout?
My keypad has a special 000 key. Is it possible to turn it into
a hotkey?
Language Syntax
When are quotation marks
used with commands and their parameters?
Double quotes (") have special meaning only within expressions. In all
other places, they are treated literally as if they were normal
characters. However, when a script launches a program or document,
the operating system usually requires quotes around any command-
line parameter that contains spaces, such as in this
example: Run, Notepad.exe "C:\My Documents\Address
List.txt".
When exactly are variable
names enclosed in percent signs?
Variable names are always enclosed in percent signs except in
cases illustrated in bold below:
1) In parameters that are input or output variables: StringLen, OutputVar, InputVar
2) On the left side of an
assignment: Var = 123abc
3) On the left side of traditional (non-expression) if-statements: If Var1 < %Var2%
4) Everywhere in expressions. For
example:
If (Var1 <>
Var2)
Var1 := Var2 + 100
When should percent signs
and commas be escaped?
Literal percent signs must be escaped by
preceding them with an accent/backtick. For example: MsgBox The current percentage is
25`%. Literal commas must also be escaped (`,) except when used in MsgBox or the
last parameter of any command (in which case the accent is permitted but not necessary).
When commas or percent signs are enclosed in quotes within an expression, the accent is permitted but not necessary. For example: Var
:= "15%".
General Troubleshooting
What can I do if AutoHotkey
won't install?
7-zip Error: Use 7-zip
or a compatible program to extract the setup files from the installer EXE, then
run setup.exe or Installer.ahk (drag and drop
Installer.ahk onto AutoHotkeyU32.exe).
AutoHotkey's installer comes packaged as a 7-zip self-extracting
archive which attempts to extract to the user's Temp directory and
execute a compiled script. Sometimes system policies or other
factors prevent the files from being extracted or executed. Usually in such
cases the message "7-zip Error" is
displayed. Manually extracting the files to a different directory may help.
Setup hangs: If the setup window comes up blank or not
at all, try one or both of the following:
Hold Ctrl or Shift when the installer starts.
If you get a UAC prompt, hold Ctrl or Shift as you click Yes/Continue. You should
get a prompt asking whether you want to install with default
options.
Install using command line options. If you have manually extracted the setup files from the
installer EXE, use either setup.exe
/S or AutoHotkeyU32.exe
Installer.ahk /S.
Other: The suggestions above cover the most common problems. For
further assistance, post on the forums.
Why do some lines in my script never execute?
Any lines you want to execute immediately when the script starts
should appear at the top of the script, prior to the first hotkey,
hotstring, or Return. For
details, see auto-execute section.
Also, a hotkey that
executes more than one line must list its first line beneath the hotkey, not on
the same line. For example:
#space:: ; Win+Spacebar
Run Notepad
WinWaitActive Untitled - Notepad
WinMaximize
return
Why doesn't my script work
on Windows xxx even though it worked on a previous version?
There are many variations
of this problem, such as:
I've
upgraded my computer/Windows and now my script won't work.
Hotkeys/hotstrings don't work when a program running as admin is
active.
Some windows refuse to be automated (e.g. Device Manager ignores
Send).
If you've switched operating systems, it is likely that something
else has also changed and may be affecting your script. For instance, if
you've got a new computer, it might have different drivers or
other software installed. If you've also updated to a newer version of
AutoHotkey, find out which version you had before and then check
the changelog and compatibility notes.
SoundGet, SoundSet, SoundGetWaveVolume and SoundSetWaveVolume behave
differently on Vista and later than on earlier versions of Windows. In particular, device numbers are different and
some components may be unavailable. Behaviour depends on the audio
drivers, which are necessarily different to the ones used on XP.
The soundcard analysis script can be used to find the correct device
numbers.
Also refer to the following
question:
How do I work around
problems caused by User Account Control (UAC)?
User Account Control (UAC) is a common cause of
problems, especially when moving from Windows XP/Vista/7 to Vista/7/8/10.
Although it is present in Windows Vista and later, it is enabled
by default on new systems or new installs, and it is more difficult to
disable on Windows 8 and later.
By default, UAC protects "elevated" programs (that is,
programs which are running as admin) from being automated by non-elevated
programs, since that would allow them to bypass security
restrictions. Hotkeys are also blocked, so for instance, a non-elevated program
cannot spy on input intended for an elevated program.
UAC may also prevent SendPlay and BlockInput from
working.
Common workarounds are as follows:
Enable the Add 'Run with UI Access' to context menus option in AutoHotkey Setup. This option can be enabled or
disabled without
reinstalling AutoHotkey by re-running AutoHotkey Setup from the
Start menu. Once it is enabled, launch your script file by right-
clicking it and selecting Run
with UI Access, or use a command line like "AutoHotkeyU32_UIA.exe"
"Your script.ahk" (but
include full paths).
Run the script as administrator. Note that this also causes any programs
launched by the script to run as administrator, and may
require the user to accept an approval prompt when launching the
script.
Disable the local security policy "Run all administrators in
Admin Approval Mode" (not recommended).
Disable UAC completely. This is not recommended, and is not
feasible on Windows 8 or later.
I can't edit my script via
tray icon because it won't start due to an error. What do I do?
You need to fix the error in your script before you can get your
tray icon back. But first, you need to find the script file.
Look for AutoHotkey.ahk in the following directories:
Your
Documents (or My Documents) folder.
The directory where you installed AutoHotkey, usually C:\Program
Files\AutoHotkey. If you are using AutoHotkey without
having installed it, look in the directory which contains
AutoHotkey.exe.
If you are running another AutoHotkey executable directly, the
name of the script depends on the executable. For example, if you are
running AutoHotkeyU32.exe, look for AutoHotkeyU32.ahk. Note that
depending on your system settings the ".ahk" part may be hidden,
but the file should have an icon like
You can usually edit a script file by right clicking it and
selecting Edit Script. If that doesn't work, you can open the file in Notepad
or
another editor.
If you launch AutoHotkey from the Start menu or by running
AutoHotkey.exe directly (without command line parameters), it will look
for a script in one of the locations shown above. Alternatively,
you can create a script file (something.ahk) anywhere you like, and run
the script file instead of running AutoHotkey.
See also Command Line Parameter "Script Filename" and Portability of AutoHotkey.exe.
How can I find and fix errors in my code?
For simple scripts,
see Debugging a Script. To show contents of a variable, use
MsgBox or
ToolTip. For complex scripts, see Interactive
Debugging.
Why is the Run command
unable to launch my game or program?
Some programs need to be
started in their own directories (when in doubt, it is usually best to do so).
For example:
Run, %A_ProgramFiles%\Some
Application\App.exe, %A_ProgramFiles%\Some Application
If the program you
are trying to start is in %A_WinDir%\System32 and you are using
AutoHotkey 32-bit on a 64-bit system, the File
System Redirector may be interfering. To work around
this, use %A_WinDir%\SysNative instead; this is a virtual directory
only visible to
32-bit programs running on 64-bit systems.
Why are the non-ASCII
characters in my script displaying or sending incorrectly?
Short answer: Save the
script as UTF-8 with BOM.
Although AutoHotkey supports Unicode text, it is optimized for backward-compatibility,
which means defaulting to the ANSI encoding rather than the more internationally recommended UTF-8.
AutoHotkey will not automatically recognize a UTF-8 file unless it begins
with a byte order mark.
In other words, UTF-8 files
which lack a byte order mark are misinterpreted, causing non-ASCII characters
to be decoded incorrectly.
To resolve this, save the
file as UTF-8 with BOM or add the /CP65001 command line switch.
To save as UTF-8 with BOM
in Notepad, select UTF-8 from the
Encoding drop-down in the Save As
dialog.
To read other UTF-8 files
which lack a byte order mark, use FileEncoding UTF-8-RAW, the *P65001 option with FileRead, or "UTF-8-
RAW" for the third parameter of FileOpen. The -RAW suffix can be omitted, but
in that case any newly created files will have a byte order
mark.
Note that INI files accessed with the standard INI commands do not
support UTF-8; they must be saved as ANSI or UTF-16.
Why do Hotstrings, Send, and Click have no
effect in certain games?
Not all games allow AHK to
send keys and clicks or receive pixel colors.
But there are some alternatives, try all the solutions mentioned
below. If all these fail, it may not be possible for AHK to work with your
game. Sometimes games have a hack and cheat
prevention measure, such as GameGuard and Hackshield. If they do, there is a
high
chance that AutoHotkey will not work with that game.
Use
SendPlay via the SendPlay command, SendMode Play and/or the hotstring option SP.
SendPlay, abc
SendMode, Play
Send, abc
:SP:btw::by the way
; or
#Hotstring SP
::btw::by the way
Note: SendPlay may have no effect at all on Windows Vista or later
if User Account Control is enabled, even if the script is
running as an administrator.
Increase SetKeyDelay. For example:
SetKeyDelay, 0, 50
SetKeyDelay, 0, 50, Play
Try ControlSend, which
might work in cases where the other Send modes fail:
ControlSend,,
abc, game_title
Try the
down and up event of a key with the various send methods:
Send {KEY
down}{KEY up}
Try the
down and up event of a key with a Sleep between
them:
Send {KEY down}
Sleep 10 ; try various
milliseconds
Send {KEY up}
How can performance be
improved for games or at other times when the CPU is under heavy load?
If a script's Hotkeys, Clicks, or Sends are
noticeably slower than normal while the CPU is under heavy load, raising the
script's process- priority may help. To do this,
include the following line near the top of the script:
Process, Priority, ,
High
My antivirus program
flagged AutoHotkey or a compiled script as malware. Is it really a virus?
Although it is certainly possible that the file has been infected,
most often these alerts are false positives, meaning that the antivirus
program is mistaken. One common suggestion is to upload the file
to an online service such as virustotal or Jotti and see what other
antivirus programs have to say. If in doubt, you could send the
file to the vendor of your antivirus software for confirmation. This might
also help us and other AutoHotkey users, as the vendor may confirm
it is a false positive and fix their product to play nice with
AutoHotkey.
False positives might be more common for compiled scripts which
have been compressed, such as with UPX (default for AutoHotkey
1.0 but not 1.1) or MPRESS (optional for AutoHotkey 1.1). As the
default AutoHotkey installation does not include a compressor,
compiled scripts are not compressed by default.
Common Tasks
Where can I find the
official build, or older releases?
See download page of AutoHotkey.
Can I run AHK from a USB
drive?
See Portability of AutoHotkey.exe. Note that if you use auto-included function libraries,
AutoHotkey.exe and the Lib folder must be up one level from Ahk2Exe.exe (e.g. \AutoHotkey.exe vs
\Compiler\Ahk2Exe.exe). Also note that Ahk2Exe saves settings to the following
registry key: HKCU\Software\AutoHotkey\Ahk2Exe.
How can the output of a
command line operation be retrieved?
Testing shows that due to file caching, a temporary file can be
very fast for relatively small outputs. In fact, if the file is deleted
immediately after use, it often does not actually get written to
disk. For example:
RunWait %ComSpec% /c dir
> C:\My Temp File.txt
FileRead, VarToContainContents, C:\My Temp File.txt
FileDelete, C:\My Temp File.txt
To avoid using a temporary file (especially if the output is
large), consider using the Shell.Exec() method as shown in the examples for the Run
command.
How can a script close,
pause, or suspend other script(s)?
First, here is an example
that closes another script:
DetectHiddenWindows On ; Allows a script's hidden main window to be
detected.
SetTitleMatchMode 2 ; Avoids the need to specify the full path of
the file below.
WinClose Script's File Name.ahk -
AutoHotkey ; Update this to reflect the
script's name (case sensitive).
To suspend or pause another script, replace the last line above with one of these:
PostMessage, 0x111, 65305,,, Script's File Name.ahk -
AutoHotkey ; Suspend.
PostMessage, 0x111, 65306,,, Script's File Name.ahk -
AutoHotkey ; Pause.
How can a repeating action
be stopped without exiting the script?
To pause or resume the
entire script at the press of a key, assign a hotkey to the Pause command as in this example:
^!p::Pause ; Press Ctrl+Alt+P to pause. Press it again
to resume.
To stop an action that is repeating inside a Loop,
consider the following working example, which is a hotkey that both starts and
stops its own repeating action. In other
words, pressing the hotkey once will start the Loop. Pressing the same hotkey
again will stop it.
#MaxThreadsPerHotkey 3
#z:: ; Win+Z hotkey (change this hotkey to suit
your preferences).
#MaxThreadsPerHotkey 1
if KeepWinZRunning ; This means an underlying thread is already
running the loop below.
{
KeepWinZRunning := false ; Signal
that thread's loop to stop.
return ; End this thread so that
the one underneath will resume and see the change made by the line above.
}
; Otherwise:
KeepWinZRunning := true
Loop
{
; The next four lines are
the action you want to repeat (update them to suit your preferences):
ToolTip, Press Win-Z
again to stop this from flashing.
Sleep 1000
ToolTip
Sleep 1000
; But leave the rest below unchanged.
if not KeepWinZRunning ;
The user signaled the loop to stop by pressing Win-Z again.
break ; Break out of this loop.
}
KeepWinZRunning := false ;
Reset in preparation for the next press of this hotkey.
return
How can context sensitive
help for AutoHotkey commands be used in any editor?
Rajat created this script.
How to detect when a web
page is finished loading?
With Internet Explorer, perhaps the most reliable method is to use
DllCall and COM as demonstrated at
www.autohotkey.com/forum/topic19256.html. On a
related note, the contents of the address bar and status bar can be retrieved
as
demonstrated at www.autohotkey.com/forum/topic19255.html.
Older, less reliable method:
The technique in the following example will work with MS Internet Explorer for
most pages. A similar technique might work in other
browsers:
Run, www.yahoo.com
MouseMove, 0, 0 ; Prevents
the status bar from showing a mouse-hover link instead of "Done".
WinWait, Yahoo! -
WinActivate
StatusBarWait,
Done, 30
if ErrorLevel
MsgBox The wait timed out or the window was closed.
else
MsgBox The page is done loading.
How can dates and times be
compared or manipulated?
The EnvAdd command can add or subtract a quantity of days, hours, minutes,
or seconds to a time-string that is in the
YYYYMMDDHH24MISS format.
The following example subtracts 7 days from the specified time: EnvAdd,
VarContainingTimestamp, -7, days.
To determine the amount of time between two dates or times, see EnvSub, which
gives an example. Also, the built-in variable
A_Now contains the current local time. Finally, there are several
built-in date/time variables, as well as the FormatTime
command to create a custom date/time string.
How can I send the current
Date and/or Time?
Use FormatTime or built-in variables for date and time.
How can I send text to a
window which isn't active or isn't visible?
Use ControlSend.
How can Winamp be
controlled even when it isn't active?
See Automating Winamp.
How can MsgBox's button names be changed?
Here is an example.
How can I change the
default editor, which is accessible via context menu or tray icon?
In the example section of Edit you will
find a script that allows you to change the default editor.
How can I save the contents of my GUI associated variables?
Use Gui Submit. For
Example:
Gui, Add, Text,, Enter some Text and press Submit:
Gui, Add, Edit, vAssociatedVar
Gui, Add, Button,, Submit
Gui, Show
Return
ButtonSubmit:
Gui, Submit, NoHide
MsgBox, Content of the edit control: %AssociatedVar%
Return
Can I draw something with
AHK?
See GDI+
standard library by tic. It's also possible with some rudimentary methods using
Gui, but in a limited way.
How can I start an action when a window appears, closes or becomes
[in]active?
Use WinWait, WinWaitClose or WinWait[Not]Active.
There are also user-created solutions such as OnWin.ahk and [How to] Hook on to Shell to receive its messages.
Hotkeys, Hotstrings, and Remapping
How do I put my hotkeys and
hotstrings into effect automatically every time I start my PC?
There are several ways to make a script (or any program) launch
automatically every time you start your PC. The easiest is to place a
shortcut to the script in the Startup folder:
1. Find the script file, select it, and press
Control+C.
2. Press Win+R to open the Run dialog, then enter shell:startup and click OK or Enter. This
will open the Startup folder for the
current user. To instead open the folder for all users, enter shell:common startup (however, in that case you must be an
administrator to proceed).
3. Right click inside the window, and click "Paste
Shortcut". The shortcut to the script should now be in the Startup folder.
I'm having trouble getting my mouse buttons working as hotkeys.
Any advice?
The left and right mouse buttons should be assignable normally
(for example, #LButton:: is the Win+LeftButton hotkey).
Similarly, the middle button and the turning of
the mouse wheel
should be assignable normally except on mice whose drivers directly control
those
buttons.
The fourth button (XButton1) and the fifth button (XButton2) might
be assignable if your mouse driver allows their clicks to be seen by the system. If they cannot be
seen -- or if your mouse has more than five buttons that you want to use -- you
can try configuring the
software that came with the mouse (sometimes accessible in the
Control Panel or Start Menu) to send a keystroke whenever you press
one of these buttons. Such a keystroke can then be defined as a
hotkey in a script. For example, if you configure the fourth button to send
Control+F1, you can
then indirectly configure that button as a hotkey by using ^F1:: in a script.
If you have a five-button mouse whose fourth and fifth buttons
cannot be seen, you can try changing your mouse driver to the default
driver included with the OS. This assumes there is such a driver
for your particular mouse and that you can live without the features
provided by your mouse's custom software.
How can Tab and Space be
defined as hotkeys?
Use the names of the keys (Tab and Space) rather than their
characters. For example, #Space is Win+Space and ^!Tab is
Control+Alt+Tab.
How can keys or mouse
buttons be remapped so that they become different keys?
This is described on the remapping page.
How do I detect the double
press of a key or button?
Use built-in variables for hotkeys as follows:
~Ctrl::
if (A_ThisHotkey =
A_PriorHotkey && A_TimeSincePriorHotkey < 200)
MsgBox double-press
return
How can a hotkey or hotstring be made
exclusive to certain program(s)? In other words, I want a certain
key to act as it normally does except when a specific window is
active.
The preferred method is #IfWinActive. For
example:
#IfWinActive, ahk_class Notepad
^a::MsgBox You pressed Control-A
while Notepad is active.
How can a prefix key be
made to perform its native function rather than doing nothing?
Consider the following
example, which makes Numpad0 into a prefix key:
Numpad0 & Numpad1::MsgBox, You
pressed Numpad1 while holding down Numpad0.
Now, to make Numpad0 send a real Numpad0 keystroke whenever it
wasn't used to launch a hotkey such as the above, add the following
hotkey:
$Numpad0::Send, {Numpad0}
The $ prefix is needed to prevent a warning dialog about an
infinite loop (since the hotkey "sends itself"). In addition, the above
action
occurs at the time the key is released.
How can the built-in Windows shortcut keys, such as Win+U (Utility
Manager) and Win+R (Run), be
changed or disabled?
Here are some examples.
Can I use wildcards or
regular expressions in Hotstrings?
Use the script by
polyethene (examples are included).
How can I use a hotkey that
is not in my keyboard layout?
See Special Keys.
My keypad has a special 000
key. Is it possible to turn it into a hotkey?
Yes. This example script makes the
000 key into an equals key. You can change the action by replacing
the Send, = line with line(s) of your choice.
Functions
Table of Contents
Introduction and Simple Examples
Parameters
Optional Parameters
Returning Values to Caller
Variadic Functions
Local Variables
Dynamically Calling a Function
Short-circuit Boolean Evaluation
Using Subroutines Within a Function
Return, Exit, and General Remarks
Using #Include to Share Functions Among Multiple Scripts
Libraries of Functions: Standard Library and User Library
Built-in Functions
Introduction and Simple
Examples
A function is similar to a subroutine (Gosub) except
that it can accept parameters (inputs) from its caller. In addition, a function
may
optionally return a value to its caller. Consider the following
simple function that accepts two numbers and returns their sum:
Add(x, y)
{
return x + y ; "Return" expects an expression.
}
The above is known as a function definition because it creates a function named "Add" (not case
sensitive) and establishes that anyone
who calls it must provide exactly two parameters (x and y). To
call the function, assign its result to a variable with the := operator. For
example:
Var := Add(2, 3) ; The number 5 will be stored in Var.
Also, a function may be called without storing its return value:
Add(2, 3)
But in this case, any value returned by the function is discarded;
so unless the function produces some effect other than its return value,
the call would serve no purpose.
Since a function call is an expression, any variable names in its parameter list should not be enclosed
in percent signs. By contrast, literal strings
should be enclosed in double quotes. For example:
if InStr(MyVar, "fox")
MsgBox The variable MyVar contains the word fox.
Finally, functions may be called in the parameters of any command
(except OutputVar and InputVar parameters such as those of
StringLen). However,
parameters that do not support expressions must use
the "% " prefix as in this example:
MsgBox % "The answer is:
" . Add(3, 2)
The "% " prefix is also permitted in parameters that
natively support expressions, but it is simply ignored.
Parameters
When a function is defined, its parameters are listed in
parentheses next to its name (there must be no spaces between its name and the
open-parenthesis). If a function does not accept any parameters,
leave the parentheses empty; for example: GetCurrentTimestamp().
ByRef Parameters: From the function's point of view, parameters
are essentially the same as local variables unless they are defined as ByRef as in this example:
Swap(ByRef Left, ByRef Right)
{
temp := Left
Left := Right
Right := temp
}
In the example above, the use of
ByRef causes each parameter to become an alias for the variable passed
in from the caller. In other
words, the parameter and the caller's variable both refer to the
same contents in memory. This allows the Swap function to alter the
caller's variables by
moving Left's contents into Right and
vice versa.
By contrast, if ByRef were not used in the example above, Left and Right would be copies of the
caller's variables and thus the Swap
function would have no external effect.
Since return can send
back only one value to a function's caller,
ByRef can be used to send back extra results. This is achieved by having
the caller pass in a variable (usually empty) in
which the function stores a value.
When passing large strings to a function, ByRef enhances performance and conserves memory by avoiding the
need to make a copy of
the string. Similarly, using ByRef to send a long string back to
the caller usually performs better than something like Return
HugeString.
[AHK_L 60+]: If something other than a modifiable variable is
passed to a ByRef parameter, the function behaves as though the
keyword "ByRef" is absent. For example, Swap(A_Index,
i) stores the value of A_Index
in i, but the value assigned to Left
is discarded once the Swap function returns.
[v1.1.01+]: The IsByRef() function can be used to determine whether the caller supplied a
variable for a given ByRef parameter.
Known limitations:
Fields of objects are not considered variables for the purposes of
ByRef. For example, if foo.bar is
passed to a ByRef parameter, it
will behave as though ByRef was omitted.
It is not possible to pass Clipboard, built-in variables, or environment variables to a function's ByRef
parameter, even when
#NoEnv is absent from the script.
Although a function may call itself recursively, if it passes one
of its own local variables or
non-ByRef parameters to itself ByRef,
the new layer's ByRef
parameter will refer to its own local variable of that name rather than the
previous layer's. However, this
issue does not occur when a function passes to itself a global variable, static variable, or ByRef parameter.
If a parameter in a function-call resolves to a variable (e.g. Var or ++Var or Var*=2), other parameters to its left or right can alter
that variable before it is passed to the function. For example, MyFunc(Var,
Var++) would unexpectedly pass 1 and 0 when Var is
initially 0, even when the function's first parameter is not ByRef. Since this behavior is
counterintuitive, it might change in a future
release.
ByRef is not directly supported in functions called by COM clients,
or when calling COM methods. Instead, the script receives or
must pass a wrapper object containing the VarType and
address of the value.
Optional Parameters
When defining a function, one or more of its parameters can be
marked as optional. This is done by appending
:= (in [v1.1.09] or later)
or =, followed by the parameter's default value, which must be one of
the following: true, false, a literal integer, a literal floating point
number, or a quoted/literal string such as
"fox" or "" (but strings in versions prior to [v1.0.46.13]
support only "").
The use of = (without a colon) is permitted for backward-compatibility, but
not recommended, and will not be permitted by AutoHotkey
v2. Regardless of which operator is used, default
values which are strings must always be enclosed in quote marks.
The following function has
its Z parameter marked optional:
Add(X, Y, Z:=0) {
return X + Y + Z
}
When the caller passes three parameters to the function above, Z's
default value is ignored. But when the caller passes only two
parameters, Z automatically receives the value 0.
It is not possible to have optional parameters isolated in the
middle of the parameter list. In other words, all parameters that lie to the
right of the first optional parameter must also be marked
optional. [AHK_L 31+]: Optional
parameters may be omitted from the middle of the parameter list when calling the function, as shown
below. For dynamic function calls and method calls, this requires [v1.1.12+].
MyFunc(1,, 3)
MyFunc(X, Y:=2, Z:=0) { ;
Note that Z must still be optional in this case.
MsgBox %X%, %Y%, %Z%
}
[v1.0.46.13+]: ByRef
parameters also support default values; for example: MyFunc(ByRef
p1 = ""). Whenever the caller omits such a
parameter, the function creates a local variable to
contain the default value; in other words, the function behaves as though the
keyword "ByRef" is absent.
Returning Values to Caller
As described in introduction, a function may optionally return a value
to its caller.
Test := returnTest()
MsgBox % Test
returnTest() {
return 123
}
If you want to return extra
results from a function, you may also use ByRef:
returnByRef(A,B,C)
MsgBox % A "," B "," C
returnByRef(ByRef val1, ByRef
val2, ByRef val3)
{
val1 := "A"
val2 := 100
val3 := 1.1
return
}
[v1.0.97+]: Objects and Arrays can be
used to return multiple values or even named values:
Test1 := returnArray1()
MsgBox % Test1[1] ","
Test1[2]
Test2 := returnArray2()
MsgBox % Test2[1] ","
Test2[2]
Test3 := returnObject()
MsgBox % Test3.id ","
Test3.val
returnArray1() {
Test :=
[123,"ABC"]
return Test
}
returnArray2() {
x := 456
y := "EFG"
return [x, y]
}
returnObject() {
Test := {id: 789, val:
"HIJ"}
return Test
}
Variadic Functions [AHK_L 60+]
When defining a function, write an asterisk after the final
parameter to mark the function as variadic, allowing it to receive a variable
number of parameters:
Join(sep, params*) {
for index,param in
params
str .= param . sep
return SubStr(str, 1, -StrLen(sep))
}
MsgBox % Join("`n",
"one", "two", "three")
When a variadic function is called, surplus parameters can be
accessed via an object which is stored in the function's final parameter. The
first surplus parameter is at params[1], the second at params[2] and so on. As with any
standard object, params.MaxIndex() can be
used to determine the highest numeric index (in this case the
number of parameters). However, if there are no parameters, MaxIndex
returns an empty string.
Notes:
The "variadic" parameter can only appear at the end of
the formal parameter list.
RegEx callouts cannot
be variadic; the "variadic" parameter is tolerated but left blank.
Callbacks pass
surplus parameters by address rather
than via an array.
Variadic Function Calls
While variadic functions can accept
a variable number of parameters, an array of parameters can be passed to any function by applying
the same syntax to a function-call:
substrings := ["one", "two",
"three"]
MsgBox % Join("`n", substrings*)
Notes:
Numbering of parameters within the source array begins at 1.
Optional parameters may be entirely omitted from the array.
The array of parameters may contain named items when calling a
user-defined function; in any other case, named items are not
supported.
The target function may also be variadic, in which case named
items are copied even if they have no corresponding formal
parameter.
This syntax can also be used when calling methods or retrieving
properties of objects; for example, Object.Property[Params*].
[v1.1.12+]: It can also be used for setting properties.
Known limitations:
Only the
right-most parameter can be expanded this way. For example, MyFunc(x,
y*) is
supported but MyFunc(x*, y) is not.
There must not be any
non-whitespace characters between the asterisk (*) and the symbol which ends the parameter list.
Local and Global Variables
Local Variables
Local variables are specific to a single function and are visible
only inside that function. Consequently, a local variable may have the
same name as a global variable and both will have separate
contents. Separate functions may also safely use the same variable names.
All local variables which
are not static are automatically freed (made empty) when the function returns.
Built-in variables such as Clipboard, ErrorLevel, and A_TimeIdle are
never local (they can be accessed from anywhere), and cannot be
redeclared.
Functions are assume-local by default. Variables accessed or
created inside an assume-local function are local by default, with the
following exceptions:
Super-global variables, including classes.
A dynamic variable reference may
resolve to an existing global variable if no local variable exists by that
name.
Commands that create pseudo-arrays may
create all elements as global even if only the first element is declared.
The default may also be
overridden as shown below (by declaring the variable or by changing the mode of
the function).
Force-local mode
[v1.1.27+]: If the function's first line is the word "local", all
variable references (even dynamic ones) are assumed to
be local unless they are declared as global inside the function.
Unlike the default mode, force-local mode has the following behavior:
Super-global
variables (including classes) cannot be accessed without declaring them inside
the function.
Dynamic variable references follow the same rules as non-dynamic
ones. Only global variables which are declared inside the
function can be accessed.
StringSplit and other commands which create pseudo-arrays follow
the same rules as non-dynamic variable references (avoiding a
common source of confusion).
The LocalSameAsGlobal warning is never raised for variables within a force-local function.
Global variables
To refer to an existing
global variable inside a function (or create a new one), declare the variable
as global prior to using it. For example:
LogToFile(TextToLog)
{
global LogFileName ; This global variable was previously given a
value somewhere outside this function.
FileAppend,
%TextToLog%`n, %LogFileName%
}
Assume-global mode: If a function needs to access or create a
large number of global variables, it can be defined to assume that all its
variables are global (except its parameters) by making its first
line either the word "global" or the declaration of a local variable.
For
example:
SetDefaults()
{
global ; This word may be omitted if the first line
of this function will be something like "local MyVar".
MyGlobal := 33 ; Assigns 33 to a global variable, first
creating the variable if necessary.
local x, y:=0, z ; Local
variables must be declared in this mode, otherwise they would be assumed
global.
}
This assume-global mode can also be used by a function to create a
global array, such as
a loop that assigns values to Array%A_Index%.
Super-global variables [v1.1.05+]: If a global declaration appears
outside of any function, it takes effect for all functions by default
(excluding force-local functions). This avoids the need to redeclare the variable in
each function. However, if a function parameter or
local variable with the same name is declared, it takes precedence
over the global variable. Variables created by the class keyword
are
also super-global.
Static variables
Static variables are always
implicitly local, but differ from locals because their values are remembered
between calls. For example:
LogToFile(TextToLog)
{
static LoggedLines = 0
LoggedLines += 1 ; Maintain a tally locally (its value is
remembered between calls).
global LogFileName
FileAppend, %LoggedLines%: %TextToLog%`n, %LogFileName%
}
Static Initializers: In versions prior to 1.0.46, all static
variables started off blank; so the only way to detect that one was being used
for
the first time was to check whether it was blank.
[v1.0.46+]: A static variable may be initialized to something other than "" by following it with := or = followed by one of the following: true, false, a literal integer, a literal floating point number, or a
literal/quoted string
such as "fox". For
example: static X:=0, Y:="fox". Each
static variable is initialized only once (before the script begins executing).
[AHK_L 58+]: Static var := expression is supported. All such expressions are evaluated immediately
before the script's auto-
execute section in the order they are encountered in the script.
Assume-static mode
[v1.0.48+]: A function may be defined to assume that all its variables are
static (except its parameters) by making its first line the word "static". For example:
GetFromStaticArray(WhichItemNumber)
{
static
static FirstCallToUs :=
true ; A static declaration's
initializer still runs only once (upon startup).
if FirstCallToUs ; Create a static array during the first
call, but not on subsequent calls.
{
FirstCallToUs := false
Loop 10
StaticArray%A_Index% := "Value
#" . A_Index
}
return StaticArray%WhichItemNumber%
}
In assume-static mode, any variable that should not be static must
be declared as local or global (with the same exceptions as for assume-
local mode,
unless force-local mode is also in effect).
[v1.1.27+]: Force-local mode can be combined with assume-static mode by specifying local and then static, as
shown below. This
allows the function to use force-local rules but create variables
as static by default.
global MyVar := "This is global"
DemonstrateForceStatic()
DemonstrateForceStatic()
{
local
static
MyVar := "This is
static"
ListVars
MsgBox
}
More about locals and
globals
Multiple variables may be
declared on the same line by separating them with commas as in these examples:
global LogFileName, MaxRetries := 5
static TotalAttempts = 0, PrevResult
[v1.0.46+]: A local or global variable may be initialized on the
same line as its declaration by following it with := or = followed by any expression (the = operator
behaves the same as := in declarations). Unlike static initializers, the initializers of
locals and globals execute every time
the function is called, but only if/when the flow of control actually reaches
them. In other words, a line like local x = 0 has the same effect as writing two
separate lines: local
x followed by x = 0.
Because the words local, global, and static are processed
immediately when the script launches, a variable cannot be conditionally
declared by means of an IF statement. In other words, a declaration inside an IF's or ELSE's block takes effect
unconditionally for all
lines between the declaration and the function's closing brace.
Also note that it is not currently possible to declare a dynamic variable
such as global Array%i%.
For commands that create pseudo-arrays (such as
StringSplit), each variable in the resulting pseudo-array is local if the assume-global
mode is not in effect or if the
pseudo-array's first element has been declared as a local variable (this is
also true if one of the function's
parameters is passed -- even if that parameter is ByRef -- because parameters are
similar to local variables). Conversely, if the first
element has been declared global, a global array is created. However, the common source of
confusion below applies even in these
cases. The first element for StringSplit is ArrayName0. For other array-creating commands such as WinGet List, the
first element is
ArrayName (i.e. without the number). [v1.1.27+]: When force-local mode is in effect, these
commands follow rules consistent with
normal variable references; that is, any pseudo-array element not
declared as global will be local even if other elements are declared
global.
Within a function (unless force-local mode is in effect), any dynamic
variable reference such as Array%i% always resolves to a local
variable unless no variable of that name exists, in which case a
global is used if it exists. If neither exists and the usage requires the
variable to be created, it is created as a local variable unless
the assume-global
mode is in effect. Consequently, a function can
create a
global array manually (by means such as Array%i%
:= A_Index) only if it has been defined as an assume-global
function.
Common source of confusion:
Any non-dynamic reference to a variable creates that variable the moment the
script launches. For
example, when used outside a function, MsgBox %Array1% creates Array1 as a global the moment the script launches.
Conversely, when used inside a function MsgBox
%Array1% creates Array1 as one of the function's locals
the moment the script launches (unless assume-
global is in effect), even if
Array and Array0 are declared global.
Dynamically Calling a Function
[v1.0.47.06+]: A function (even a built-in
function) may be
called dynamically via percent signs. For example, %Var%(x,
"fox") would call the
function whose name is contained in Var. Similarly, Func%A_Index%() would call Func1() or Func2(), etc., depending on the
current value of A_Index.
[v1.1.07.00+]: Var in %Var%() can
contain a function name or a function object. If the function does not exist, the default base object's
__Call meta-function is invoked instead.
If the function cannot be called due to one of the reasons below,
the evaluation of the expression containing the call stops silently and
prematurely, which may lead to inconsistent results:
Calling a nonexistent function, which can be avoided by using If IsFunc(VarContainingFuncName). Except for built-in
functions, the called function's definition must exist explicitly in
the script by means such as #Include or a
non-dynamic call to a
library function.
Passing too few parameters, which can be avoided by checking IsFunc()'s return value (which is
the number of mandatory
parameters plus one). [v1.0.48+]:
Note that passing too many parameters is tolerated; each extra parameter is
fully evaluated
(including any calls to functions) and then discarded.
Finally, a dynamic call to a function is slightly slower than a
normal call because normal calls are resolved (looked up) before the script
begins running.
Short-circuit Boolean
Evaluation
When AND, OR, and the ternary operator are used within an expression, they short-circuit to enhance performance (regardless of whether
any function calls are present). Short-circuiting
operates by refusing to evaluate parts of an expression that cannot possibly
affect its final result. To illustrate the
concept, consider this example:
if (ColorName <> "" AND not FindColor(ColorName))
MsgBox %ColorName% could
not be found.
In the example above, the FindColor() function never gets called
if the ColorName variable is empty. This is because the left side of the
AND would be false, and thus its right side would be
incapable of making the final outcome true.
Because of this behavior, it's important to realize that any
side-effects produced by a function (such as altering a global variable's
contents) might never occur if that function is called on the
right side of an AND or OR.
It should also be noted that short-circuit evaluation cascades
into nested ANDs and ORs.
For example, in the following expression, only
the leftmost comparison occurs whenever ColorName is blank. This is because the left side would then be
enough to determine the final answer with
certainty:
if (ColorName = "" OR FindColor(ColorName,
Region1) OR FindColor(ColorName, Region2))
break ; Nothing to search for, or a match was
found.
As shown by the examples above, any expensive (time-consuming)
functions should generally be called on the right side of an AND or
OR to enhance
performance. This technique can also be used to prevent a function from being
called when one of its parameters would be passed a value it considers inappropriate, such as an empty
string.
[v1.0.46+]: The ternary conditional operator (?:) also short-circuits by not
evaluating the losing branch.
Using Subroutines Within a Function
Although a function cannot contain definitions of other functions, it can contain subroutines. As with other
subroutines, use Gosub to
launch them and Return to
return (in which case the Return would belong to the Gosub and not the
function).
Known limitation: Currently, the name of each subroutine (label)
must be unique among those of the entire script. The program will
notify you upon launch if there are duplicate labels.
If a function uses Gosub to jump
to a public subroutine (one that lies outside of the function's braces), all
variables outside are global and the
function's own local variables are
not accessible until the subroutine returns. However, A_ThisFunc will still
contain the name of the
function.
Although Goto cannot
be used to jump from inside a function to outside, it is possible for a
function to Gosub an
external/public
subroutine and then do a Goto from there.
Although the use of Goto is
generally discouraged, it can be used inside a function to jump to another
position within the same function. This can
help simplify complex functions that have many points of return, all of which
need to do some clean-up prior to returning.
A function may contain externally-called subroutines such as timers, GUI g-labels, and menu items. This is
generally done to encapsulate them in a
separate file for use with #Include,
which prevents them from interfering with the script's auto-execute section. However, the
following limitations apply:
Such subroutines should use only static and global
variables (not locals) if their function is ever called normally. This is because a
subroutine thread that
interrupts a function-call thread (or vice versa) would be able to change the
values of local variables seen by
the interrupted thread. Furthermore, any time a function returns
to its caller, all of its local variables are made blank to free their
memory.
Such subroutines should use only global
variables (not static
variables) as GUI control variables.
When a function is entered by a subroutine thread, any
references to dynamic variables made by
that thread are treated as globals
(including commands that create arrays).
Return, Exit, and General
Remarks
If the flow of execution within a function reaches the function's
closing brace prior to encountering a Return, the
function ends and
returns a blank value (empty string) to its caller. A blank value
is also returned whenever the function explicitly omits Return's
parameter.
When a function uses the Exit command
to terminate the current thread, its caller does not receive a return value at all. For example,
the
statement Var :=
Add(2, 3) would leave Var unchanged if Add() exits. The same thing happens if a function causes a runtime
error
such as running a
nonexistent file (when UseErrorLevel is not
in effect).
A function may alter the
value of ErrorLevel for the
purpose of returning an extra value that is easy to remember.
To call a function with one or more blank values (empty strings),
use an empty pair of quotes as in this example: FindColor(ColorName, "").
Since calling a function does not start a new thread, any
changes made by a function to settings such as
SendMode and
SetTitleMatchMode will go
into effect for its caller too.
The caller of a function may pass a nonexistent variable or array element
to it, which is useful when the function expects the
corresponding parameter to be ByRef. For example, calling GetNextLine(BlankArray%i%) would create the variable BlankArray%i%
automatically as a local or global (depending on
whether the caller is inside a function and whether it has the assume-global mode in
effect).
When used inside a function, ListVars displays
a function's local variables along with their contents.
This can help debug a script.
Style and Naming Conventions
You might find that complex functions are more readable and
maintainable if their special variables are given a distinct prefix. For
example, naming each parameter in a function's parameter list with
a leading "p" or "p_" makes their special nature easy to
discern at a
glance, especially when a function has several dozen local
variables competing for your attention. Similarly, the
prefix "r" or "r_" could be used for ByRef
parameters, and "s" or
"s_" could be used for static variables.
The One True Brace (OTB) style may optionally be used to define functions. For example:
Add(x, y) {
return x + y
}
Using #Include to Share
Functions Among Multiple Scripts
The #Include
directive may be used (even at the top of a script) to load functions from an external file.
Explanation: When the script's flow of execution encounters a
function definition, it jumps over it (using an instantaneous method) and
resumes execution at the line after its closing brace.
Consequently, execution can never fall into a function from above, nor does the
presence of one or more functions at the very top of a script
affect the auto-execute section.
Libraries of Functions:
Standard Library and User Library [v1.0.47+]
A script may call a
function in an external file without having to use #Include. For
this to work, a file of the same name as the function
must exist in one of the
following library directories:
%A_ScriptDir%\Lib\ ; Local library - requires [AHK_L 42+].
%A_MyDocuments%\AutoHotkey\Lib\ ;
User library.
directory-of-the-currently-running-AutoHotkey.exe\Lib\ ; Standard library.
For example, if a script calls a nonexistent function MyFunc(), the program searches for
a file named "MyFunc.ahk" in the user library. If
not found there, it searches for it in the standard
library. If a match is still not found and the function's name contains an
underscore (e.g. MyPrefix_MyFunc), the
program searches both libraries for a file named MyPrefix.ahk and
loads it if it exists. This allows
MyPrefix.ahk to contain both the
function MyPrefix_MyFunc and other related functions whose names start with MyPrefix_.
[AHK_L 42+]: The local library
is supported and is searched before the user library and standard library.
Only a direct function call such as MyFunc() can cause a library to be auto-included. If the function is only
called dynamically or
indirectly, such as by a timer or GUI event, the library must be
explicitly included in the script. For
example: #Include
<MyFunc>
Although a library file generally contains only a single function
of the same name as its filename, it may also contain private functions
and subroutines that are called only by it. However, such
functions should have fairly distinct names because they will still be in the
global namespace; that is, they will be callable from anywhere in
the script.
If a library file uses #Include, the
working directory for #Include is the library file's own directory. This can be
used to create a redirect to a larger
library file that contains that function and others related to it.
The script compiler (ahk2exe) also supports library functions. However, it requires that a copy
of AutoHotkey.exe exist in the directory above the compiler directory (which is normally the case).
If AutoHotkey.exe is absent, the compiler still works but library functions are
not automatically included.
Functions included from a library perform just as well as other
functions because they are pre-loaded before the script begins executing.
Built-in Functions
Any optional parameters at the end of a built-in function's
parameter list may be completely omitted. For example, WinExist("Untitled
- Notepad") is valid because its other
three parameters would be considered blank.
A built-in function is overridden if the script defines its own
function of the same name. For example, a script could have its own custom
WinExist() function that is called instead of the
standard one. However, the script would then have no way to call the original
function.
External functions that
reside in DLL files may be called with DllCall().
To get more details about a particular built-in function below,
simply click on its name.
Frequently-used Functions
Function Description
FileExist Checks for the existence of a file or folder and returns its
attributes.
GetKeyState Returns true (1) if the specified key is down and false (0) if it
is up.
InStr Searches for a given occurrence of a string, from the left or the
right.
RegExMatch Determines whether a string contains a pattern (regular
expression).
RegExReplace Replaces occurrences of a pattern (regular expression) inside a
string.
StrLen Retrieves the count of how many characters are in a string.
StrReplace Replaces occurrences of the specified substring with a new string.
StrSplit Separates a string into an array of substrings using the specified
delimiters.
SubStr Retrieves one or more characters from the specified position in a
string.
WinActive Checks if the specified window exists and is currently active
(foremost), and returns its Unique ID (HWND).
WinExist Checks if a matching window exists and returns the Unique ID
(HWND) of the first matching window.
Miscellaneous Functions
Function Description
Asc Returns the numeric value of the first byte or UTF-16 code unit in
the specified string.
Func Retrieves a reference to the specified function.
GetKeyName/VK/SCRetrieves the name/text, virtual key code or scan code of a key.
IsByRef Returns a non-zero number if a ByRef parameter of a function was
supplied with the specified variable.
IsFunc Returns a non-zero number if the specified function exists in the
script.
IsLabel Returns a non-zero number if the specified label exists in the
script.
IsObject Returns a non-zero number if the specified value is an object.
ListView Functions to add, insert, modify or delete ListView rows/colums,
or to get data from them.
NumGet Returns the binary number stored at the specified address+offset.
NumPut Stores a number in binary format at the specified address+offset.
OnMessage Monitors a message/event.
Ord Returns the ordinal value (numeric character code) of the first
character in the specified string.
StrGet Copies a string from a memory address, optionally converting it
between code pages.
StrPut Copies a string to a memory address, optionally converting it
between code pages.
RegisterCallback Creates a machine-code address that when called, redirects the
call to a function in the script.
TreeView Functions to add, modify or delete TreeView items, or to get data
from them.
Trim Trims characters from the beginning and/or end of a string.
VarSetCapacity Enlarges a variable's holding capacity or frees its memory.
Math
Function Description
Abs Returns the absolute value of Number.
Ceil Returns Number rounded up to the nearest integer (without any .00
suffix).
Exp Returns e (which is approximately 2.71828182845905) raised to the Nth power.
Floor Returns Number rounded down to the nearest integer (without any
.00 suffix).
Log Returns the logarithm (base 10) of Number.
Ln Returns the natural logarithm (base e) of Number.
Max / Min Returns the highest/lowest value of one or more numbers.
Mod Returns the remainder when Dividend is divided by Divisor.
Round Returns Number rounded to N
decimal places.
Sqrt Returns the square root of Number.
Sin / Cos / Tan Returns the trigonometric sine/cosine/tangent of Number.
ASin / ACos / ATanReturns the arcsine/arccosine/arctangent in radians.
Other Functions
Polyethene's Command Functions: Provides a callable function for each AutoHotkey command that
has an OutputVar. This library can be included
in any script via #Include.
Advanced Hotkey Features
Table of Contents
General
Remap easy to reach but rarely used keys
Use any keys as modifiers
Make the mouse wheel perform alt-tabbing
Make a keyboard key become a mouse button
Make your hotkeys context-sensitive
Define abbreviations that expand as you type them
Gaming
Reduce wear and tear on your fingers
Create mouse hotkeys
Create "pass-through" hotkeys
Automate game actions on the screen
Use the keyboard hook
Related Topics
General
Remap easy to reach but
rarely used keys
Some of the easiest keys to reach on the keyboard are also the
least frequently used. Make these keys do something useful! For example,
if you rarely use the right Alt key, make it perform the
action you do most often:
RAlt::
MsgBox You pressed the right ALT key.
return
You can even do the above without losing the native function of
the right Alt key by assigning the right Alt key to be a
"prefix" for at
least one other hotkey. In the below example, the right Alt has become a prefix, which
automatically allows it to modify all
other keys as it normally would. But if you
press and release the right Alt key without having used it to modify another
key, its hotkey action (above) will take
effect immediately:
RAlt & j::AltTab
Use any keys as modifiers
Don't be limited to using only Ctrl, Alt, Shift, and Win as modifiers; you can combine any
two keys or mouse buttons to form a custom hotkey. For example: Hold down Numpad0 and press Numpad1 to
launch a hotkey (Numpad0 & Numpad1::); hold down CapsLock and
press another key, or click a mouse button (CapsLock & RButton::). In
this case, the CapsLock key's state (on or off) is not changed
when it is used to launch the hotkey. For details, see custom combinations of keys.
Make the mouse wheel
perform alt-tabbing
Convert the mouse wheel (or any other keys of your choice) into a
complete substitute for Alt-Tab. Click the wheel to show or hide the
menu, and turn it to navigate through the menu. The wheel will
still function normally whenever the Alt-Tab menu isn't visible. Syntax:
MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab
Make a keyboard key become
a mouse button
Make a keyboard key become a mouse button, or have an action
repeated continuously while you're holding down a key or mouse
button. See the remapping page for examples.
Make your hotkeys
context-sensitive
Have your easiest-to-reach hotkeys perform an action appropriate
to the type of window you're working with. In the following example,
the right Ctrl key performs a different
action depending on whether Notepad or Calculator is the active window:
#IfWinActive ahk_class Notepad
RControl::WinMenuSelectItem, , ,
File, Save ; Save the current file in
Notepad.
#IfWinActive Calculator
RControl::Send, ^c!{tab}^v ;
Copy the Calculator's result into the previously active window.
See #IfWinActive for
details.
Define abbreviations that
expand as you type them
Also known as hotstrings. No
special training or scripting experience is needed. For example, a script
containing the following lines
would expand ceo, cfo, and btw wherever you type them:
::ceo::Chief Executive Officer
::cfo::Chief Financial Officer
::btw::by the way
Gaming
Reduce wear and tear on
your fingers
Reduce wear and tear on your fingers by using virtually any key as a
hotkey, including single letters, arrow keys, Numpad keys, and even
the modifier keys themselves (Ctrl/Alt/Win/Shift).
Create mouse hotkeys
Create mouse hotkeys, including the mouse wheel button (MButton)
and the turning of the wheel up/down or left/right (WheelUp,
WheelDown, WheelLeft, and WheelRight). You can also combine a
keyboard key with a mouse button. For example, control-right-
button would be expressed as ^RButton::.
Create
"pass-through" hotkeys
For example, the left mouse button can trigger a hotkey action
even while the click itself is being sent into the game normally (syntax:
~LButton::).
Automate game actions on
the screen
Use commands such as PixelSearch, PixelGetColor, and ImageSearch to automate game actions.
Use the keyboard hook
Have the option of using the keyboard hook to
implement hotkeys, which might be more responsive than other hotkey methods
while the CPU is under load in a game. The
hook might also be able to override any restrictions a game may have about
which keys can be
"mapped" to game actions.
Related Topics
Hotkeys
(Mouse, Joystick and Keyboard Shortcuts)
Table of
Contents
Introduction and Simple Examples
Hotkey Modifier Symbols
Context-sensitive Hotkeys
Custom Combinations
Other Features
Mouse Wheel Hotkeys
Hotkey Tips and Remarks
Alt-Tab Hotkeys
Function Hotkeys [v1.1.20+]
Introduction
and Simple Examples
Hotkeys are sometimes referred to as shortcut keys because of
their ability to easily trigger an action (such as launching a program or keyboard macro). In the
following example, the hotkey Win+N is configured to launch Notepad. The pound sign [#] stands for
the Win key, which is known as a modifier:
#n::
Run Notepad
return
In the final line above, return serves
to finish the hotkey. However, if a hotkey needs to execute only a single line,
that line can be listed to the right of the double- colon. In other words, the
return is implicit:
#n::Run Notepad
To use more than one
modifier with a hotkey, list them consecutively (the order does not matter).
The following example uses ^!s to indicate Control+Alt+S:
^!s::
Send Sincerely,{enter}John Smith ; This line sends keystrokes to the active
(foremost) window.
return
Hotkey
Modifier Symbols
You can
use the following modifier symbols to define hotkeys:
Symbol Description
Win (Windows logo key).
[v1.0.48.01+]: For Windows
Vista and later, hotkeys that include the Win key (e.g. #a) will wait
for the Win key to be released before sending any text
#
containing an L keystroke. This prevents usages of Send within
such a hotkey from locking the PC. This behavior applies to all sending modes
except SendPlay (which doesn't need it) and blind mode.
[v1.1.29+]: Text mode
is also excluded.
Note: Pressing a hotkey which includes the Win key may result in extra
simulated keystrokes (Ctrl by default). See #MenuMaskKey.
Alt
Note: Pressing a hotkey which includes the Alt key may result in extra
simulated keystrokes (Ctrl by default). See #MenuMaskKey.
^ Control
+ Shift
& An
ampersand may be used between any two keys or mouse buttons to combine them
into a custom hotkey. See below for details.
< Use the left
key of the pair. e.g. <!a is the same as !a except that only the left Alt key will trigger it.
> Use the
right key of the pair.
AltGr (alternate graving). If your keyboard layout
has AltGr instead of a right Alt key, this series of
symbols can usually be used to stand for AltGr. For example:
<^>!m::MsgBox You pressed
AltGr+m.
<^>!
*
<^<!m::MsgBox You pressed LeftControl+LeftAlt+m.
Alternatively, to make AltGr itself
into a hotkey, use the following hotkey (without any hotkeys like the above
present):
LControl & RAlt::MsgBox You
pressed AltGr itself.
Wildcard: Fire the hotkey even if extra
modifiers are being held down. This is often used in conjunction with remapping keys or buttons. For example:
*#c::Run Calc.exe ; Win+C, Shift+Win+C, Ctrl+Win+C, etc. will
all trigger this hotkey.
*ScrollLock::Run Notepad ;
Pressing ScrollLock will trigger this hotkey even when modifier key(s) are
down.
Wildcard hotkeys always use the keyboard hook, as do any hotkeys
eclipsed by a wildcard hotkey. For example, the presence of *a:: would
cause ^a:: to always use
the hook.
~
$
UP
When the hotkey fires, its key's native function will not be
blocked (hidden from the system). In both of the below examples, the user's
click of the mouse button will be sent to the active
window:
~RButton::MsgBox You clicked the
right mouse button.
~RButton & C::MsgBox You pressed C while holding down the
right mouse button.
Unlike the other prefix symbols, the tilde prefix is allowed to be
present on some of a hotkey's variants but
absent on others. However, if a tilde is applied to the prefix key of
any custom combination which has not been turned off or suspended, it affects
the behavior of that prefix key for all combinations.
Special hotkeys that are
substitutes for alt-tab always
ignore the tilde prefix.
[v1.1.14+]: If the tilde prefix is applied to a custom modifier
key (prefix
key) which
is also used as its own hotkey, that hotkey will fire when the key is
pressed instead of being delayed until the key is released. For
example, the ~RButton hotkey above is fired as soon as the button is pressed. Prior to
[v1.1.14] (or without the tilde prefix), it was fired when the
button was released, but only if the RButton & C combination was not activated.
If the tilde prefix is applied only to the custom combination and
not the non-combination hotkey, the key's native function will still be
blocked. For
example, in the script below, holding Menu will show the ToolTip and will not trigger a context menu:
AppsKey::ToolTip Press < or > to cycle through windows.
AppsKey Up::ToolTip
~AppsKey & <::Send !+{Esc}
~AppsKey & >::Send !{Esc}
If at least one variant of
a keyboard hotkey has the tilde modifier, that hotkey always uses the keyboard
hook.
This is usually only necessary if the script uses the Send command
to send the keys that comprise the hotkey itself, which might otherwise cause
it to
trigger itself. The $ prefix forces the keyboard hook to be
used to implement this hotkey, which as a side-effect prevents the Send command from
triggering it. The $ prefix is equivalent to
having specified #UseHook somewhere above the definition of this hotkey.
The $ prefix has no effect for mouse hotkeys, since they always
use the mouse hook. It also has no effect for hotkeys which already require the
keyboard
hook, including any keyboard hotkeys with the tilde (~) or wildcard (*) modifiers, key-up hotkeys
and custom combinations. To determine whether a
particular hotkey uses the keyboard hook, use ListHotkeys.
[v1.1.06+]: #InputLevel and SendLevel provide additional control over which hotkeys and hotstrings are
triggered by the Send command.
The word UP may follow the name of a hotkey to cause the hotkey to
fire upon release of the key rather than when the key is pressed down. The
following example remaps
the left Win key to become the left Control key:
*LWin::Send {LControl down}
*LWin Up::Send {LControl up}
"Up" can also be used with normal hotkeys as in this
example: ^!r Up::MsgBox
You pressed and released Ctrl+Alt+R. It also works with
combination hotkeys (e.g. F1 & e Up::)
Limitations: 1) "Up" does not work with joystick buttons; and 2)
An "Up" hotkey without a normal/down counterpart hotkey will
completely take over that key to
prevent it from getting stuck down. One way to prevent this is to add a tilde prefix (e.g. ~LControl
up::)
"Up" hotkeys and
their key-down counterparts (if any) always use the keyboard hook.
On a related note, a technique similar to the above is to make a
hotkey into a prefix key. The advantage is that although the hotkey will fire
upon release, it will do so only if you did not
press any other key while it was held down. For example:
LControl & F1::return ; Make left-control a prefix by using
it in front of "&" at least once.
LControl::MsgBox You released LControl without having used it to
modify any other key.
Note: See
the Key List for a
complete list of keyboard keys and mouse/joystick buttons.
Multiple
hotkeys can be stacked vertically to have them perform the same action. For
example:
^Numpad0::
^Numpad1::
MsgBox Pressing either Control+Numpad0 or Control+Numpad1 will
display this message.
return
A key or key-combination
can be disabled for the entire system by having it do nothing. The following
example disables the right-side Win key:
RWin::return
Context-sensitive Hotkeys
The
directives #IfWinActive/Exist and #If can be
used to make a hotkey perform a different action (or none at all) depending on
a specific condition. For example:
#IfWinActive, ahk_class Notepad
^a::MsgBox You pressed Ctrl-A while Notepad is active. Pressing
Ctrl-A in any other window will pass the Ctrl-A keystroke to that window.
#c::MsgBox You pressed Win-C while Notepad is active.
#IfWinActive
#c::MsgBox You pressed
Win-C while any window except Notepad is active.
#If MouseIsOver("ahk_class
Shell_TrayWnd")
WheelUp::Send {Volume_Up}
; Wheel over taskbar: increase/decrease volume.
WheelDown::Send {Volume_Down} ;
Custom
Combinations
You can define a custom combination of two keys (except joystick
buttons) by using " & " between them. In the below example, you
would hold down Numpad0
then press the second key to trigger the hotkey:
Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding
down Numpad0.
Numpad0 & Numpad2::Run Notepad
The prefix key loses its native function: In the above example,
Numpad0 becomes a prefix key; but this also causes Numpad0 to lose
its original/native function
when it is pressed by itself. To avoid this, a script may
configure Numpad0 to perform a new action such as one of the following:
Numpad0::WinMaximize A ; Maximize the active/foreground window.
Numpad0::Send
{Numpad0} ; Make the release of Numpad0
produce a Numpad0 keystroke. See comment below.
Fire on release: The
presence of one of the above custom combination hotkeys causes the release of
Numpad0 to perform the indicated action, but only if you did
not press any other keys while Numpad0 was being held down.
[v1.1.14+]: This behaviour can be avoided by applying the tilde prefix to either hotkey.
Modifiers: Unlike a normal hotkey, custom combinations act as
though they have the wildcard (*) modifier by default. For example, 1 & 2:: will activate even if
Ctrl or Alt is held down when 1 and 2 are pressed, whereas ^1:: would be activated only by Ctrl+1 and not Ctrl+Alt+1.
For standard modifier keys, normal hotkeys typically work as well
or better than "custom" combinations. For example, <+s:: is
recommended over LShift & s::.
Combinations of three or more keys are not supported.
Combinations which your keyboard hardware supports can usually be detected by
using #If and GetKeyState,
but the results may be inconsistent. For example:
; Press AppsKey and Alt in any order, then slash (/).
#if GetKeyState("AppsKey", "P")
Alt &
/::MsgBox Hotkey activated.
; If the keys are swapped, Alt must be pressed first (use one at a
time):
#if GetKeyState("Alt", "P")
AppsKey &
/::MsgBox Hotkey activated.
; [ & ] & \::
#if GetKeyState("[") &&
GetKeyState("]")
\::MsgBox
Keyboard hook: Custom
combinations involving keyboard keys always use the keyboard hook, as do any
hotkeys which use the prefix key as a suffix. For example,
a & b:: causes ^a:: to always use the hook.
Other
Features
NumLock, CapsLock, and
ScrollLock: These keys may be forced
to be "AlwaysOn" or "AlwaysOff". For example: SetNumLockState AlwaysOn.
Overriding Explorer's hotkeys: Windows' built-in hotkeys such as Win+E (#e) and
Win+R (#r) can be individually overridden simply by
assigning them to an action in the
script. See the override page for details.
Substitutes
for Alt-Tab: Hotkeys can provide an alternate means of alt-tabbing. For
example, the following two hotkeys allow you to alt-tab with your right hand:
RControl & RShift::AltTab ; Hold down right-control then press
right-shift repeatedly to move forward.
RControl & Enter::ShiftAltTab ; Without even having to release
right-control, press Enter to reverse direction.
For more details, see Alt-Tab.
Mouse Wheel Hotkeys
Hotkeys that fire upon turning the mouse wheel are supported via
the key names WheelDown and WheelUp. [v1.0.48+]: WheelLeft and WheelRight are
also
supported, but have no effect on operating systems older than
Windows Vista. Here are some examples of mouse wheel hotkeys:
MButton & WheelDown::MsgBox You turned the mouse wheel down
while holding down the middle button.
^!WheelUp::MsgBox You rotated the wheel up while holding down
Control+Alt.
[v1.0.43.03+]: The built-in variable A_EventInfo contains the amount by which the wheel was turned,
which is typically 1. However, A_EventInfo can be greater or
less than 1 under the following circumstances:
If the mouse hardware reports distances of less than one notch,
A_EventInfo may contain 0;
If the wheel is being turned quickly (depending on type of mouse),
A_EventInfo may be greater than 1. A hotkey like the following can help analyze
your
mouse: ~WheelDown::ToolTip %A_EventInfo%.
Some of the most useful hotkeys for the mouse wheel involve alternate
modes of scrolling a window's text. For example, the following pair of hotkeys
scrolls
horizontally instead of vertically when you turn the wheel while
holding down the left Control key:
~LControl & WheelUp:: ;
Scroll left.
ControlGetFocus,
fcontrol, A
Loop 2 ;
<-- Increase this value to scroll faster.
SendMessage, 0x114, 0,
0, %fcontrol%, A ; 0x114 is WM_HSCROLL
and the 0 after it is SB_LINELEFT.
return
~LControl & WheelDown:: ; Scroll right.
ControlGetFocus,
fcontrol, A
Loop 2 ;
<-- Increase this value to scroll faster.
SendMessage, 0x114, 1,
0, %fcontrol%, A ; 0x114 is WM_HSCROLL
and the 1 after it is SB_LINERIGHT.
return
Finally, since mouse wheel hotkeys generate only down-events
(never up-events), they cannot be used as key-up hotkeys.
Hotkey Tips and Remarks
Each numpad key can be made to launch two different hotkey
subroutines depending on the state of NumLock. Alternatively,
a numpad key can be made to launch the same
subroutine regardless of the NumLock state.
For example:
NumpadEnd::
Numpad1::
MsgBox, This hotkey is launched regardless of whether NumLock is
on.
return
If the tilde (~) operator is used
with a prefix
key even
once, it changes the behavior of that prefix key for all combinations. For
example, in both of the below
hotkeys, the active window will receive all right-clicks even
though only one of the definitions contains a tilde:
~RButton & LButton::MsgBox You pressed the left mouse button
while holding down the right.
RButton & WheelUp::MsgBox You turned the mouse wheel up while
holding down the right button.
The Suspend command
can temporarily disable all hotkeys except for ones you make exempt. For greater
selectivity, use #IfWinActive/Exist.
By means of the Hotkey command,
hotkeys can be created dynamically while the script is running. The Hotkey
command can also modify, disable, or enable the
script's existing hotkeys individually.
Joystick hotkeys do not currently support modifier prefixes such
as ^ (Control) and # (Win). However, you can use GetKeyState to mimic
this effect as shown in the following
example:
Joy2::
if not GetKeyState("Control") ; Neither the left nor right Control key is
down.
return ; i.e. Do nothing.
MsgBox You pressed the first joystick's second button while
holding down the Control key.
return
There may
be times when a hotkey should wait for its own modifier keys to be released
before continuing. Consider the following example:
^!s::Send {Delete}
Pressing Control+Alt+S would cause the system to behave as though you pressed Control+Alt+Delete (due to the system's aggressive detection of
Ctrl+Alt+Delete). To work around this, use KeyWait to wait for the keys to be released; for example:
^!s::
KeyWait Control
KeyWait Alt
Send {Delete}
return
If a hotkey label like #z:: produces
an error like "Invalid Hotkey", your system's keyboard
layout/language might not have the specified character ("Z" in this
case). Try using a different character
that you know exists in your keyboard layout.
A hotkey label can be used
as the target of a Gosub or Goto. For
example: Gosub ^!s.
One common use for hotkeys is to start and stop a repeating
action, such as a series of keystrokes or mouse clicks. For an example of this,
see this FAQ topic.
Finally, each script is quasi multi-threaded, which allows a new hotkey to be launched even when a previous
hotkey subroutine is still running. For example, new
hotkeys can be launched even while a MsgBox is being
displayed by the current hotkey.
Alt-Tab
Hotkeys
Each Alt-Tab hotkey must be a combination of two keys, which is
typically achieved via the ampersand symbol (&). In the following example,
you would hold
down the right Alt key and press J or K to navigate the alt-tab menu:
RAlt & j::AltTab
RAlt & k::ShiftAltTab
AltTab
and ShiftAltTab are two of the special commands that are only recognized when
used on the same line as a hotkey. Here is the complete list:
AltTab: If the alt-tab menu is visible, move forward in it.
Otherwise, display the menu (only if the hotkey is an "&"
combination of two keys; otherwise, it does
nothing).
ShiftAltTab:
Same as above except move backward in the menu.
AltTabAndMenu:
If the alt-tab menu is visible, move forward in it. Otherwise, display the
menu.
AltTabMenuDismiss: Close the Alt-tab menu.
To illustrate the above, the mouse wheel can be made into an
entire substitute for Alt-tab. With the following hotkeys in effect, clicking
the middle button displays
the menu and turning the wheel navigates through it:
MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab
To cancel a hotkey-invoked Alt-tab menu without activating the
selected window, use a hotkey such as the following. It might require
adjustment depending on: 1) the means by
which the alt-tab menu was originally displayed; and 2) whether the script has
the keyboard hook installed.
LCtrl & CapsLock::AltTab
!MButton:: ; Middle mouse button.
The ! prefix makes it fire while the Alt key is down (which it is if the
alt-tab menu is visible).
IfWinExist ahk_class #32771
; Indicates that the alt-tab menu is present on the screen.
Send !{Escape}{Alt up}
return
Currently, all special Alt-tab actions must be assigned directly
to a hotkey as in the examples above (i.e. they cannot be used as though they
were commands). They are not affected by #IfWin or #If.
Custom alt-tab actions can also be created via hotkeys. In the
following example, you would press F1 to
display the menu and advance forward in it. Then you would
press F2 to activate the selected window (or press Escape to cancel):
*F1::Send {Alt down}{tab} ;
Asterisk is required in this case.
!F2::Send {Alt up} ;
Release the Alt key, which activates the selected window.
~*Escape::
IfWinExist
ahk_class #32771
Send {Escape}{Alt
up} ; Cancel the menu without activating
the selected window.
return
Function
Hotkeys [v1.1.20+]
One or
more hotkeys can be assigned a function by simply defining it immediately after the hotkey label as in
this example:
; Ctrl+Shift+O to open containing
folder in Explorer.
; Ctrl+Shift+E to
open folder with current file selected.
; Supports SciTE
and Notepad++.
^+o::
^+e::
editor_open_folder() {
WinGetTitle, path, A
if RegExMatch(path,
"\*?\K(.*)\\[^\\]+(?= [-*] )", path)
if
(FileExist(path) && A_ThisHotkey = "^+e")
Run
explorer.exe /select`,"%path%"
else
Run explorer.exe
"%path1%"
}
[v1.1.28+]:
Hotstrings can also be defined this way. Multiple hotkeys or hotstrings can be
stacked together to call the same function.
There must only be whitespace, comments or directives between the
hotkey/hotstring labels or label and the function. Hotkey/hotstring labels
defined this way are not visible to IsLabel, Gosub or
other commands; however, the auto-execute section ends at the first hotkey/hotstring even if it is assigned
a function.
The main benefit of using a function is that local variables can
be used, which avoids conflicts when two or more hotkeys use the same variable
names for different purposes. It also encourages
self-documenting hotkeys, like in the code above where the function name
describes the hotkey.
The Hotkey command
can also be used to assign a function or function object to a hotkey.
Hotstrings
Table of Contents
Introduction and Simple Examples
Ending Characters
Options
Long Replacements
Context-sensitive Hotstrings
AutoCorrect
Remarks
Function Hotstrings [v1.1.28+]
Hotstring Helper
Introduction and Simple
Examples
Although hotstrings are mainly used to expand abbreviations as you
type them (auto-replace), they can also be used to launch any scripted action.
In this respect, they are similar to hotkeys except that
they are typically
composed of more than one character (that is, a string).
To define a hotstring,
enclose the triggering abbreviation between pairs of colons as in this example:
::btw::by the way
In the above example, the abbreviation btw will be automatically
replaced with "by the way" whenever you type it (however, by default
you must type an ending character after
typing btw, such as Space, ., or Enter).
The "by the way" example above is known as an
auto-replace hotstring because the typed text is automatically erased and
replaced by the string specified after the second pair of colons. By contrast,
a hotstring may also be defined to perform any custom
action as in the following examples. Note that the commands must appear beneath
the hotstring:
::btw::
MsgBox You typed "btw".
return
:*:]d:: ; This hotstring
replaces "]d" with the current date and time via the commands below.
FormatTime,
CurrentDateTime,, M/d/yyyy h:mm tt ; It will look like 9/1/2005 3:53 PM
SendInput %CurrentDateTime%
return
Even though the two examples above are not auto-replace
hotstrings, the abbreviation you type is erased by default. This is done via
automatic backspacing, which can be disabled via the b0 option.
Ending Characters
Unless the asterisk option is in effect, you must type an ending character after a
hotstring's abbreviation to trigger it. Ending characters initially consist of
the following: -()[]{}':;"/\,.?!`n `t (note that `n is Enter, `t is Tab, and there is a plain space
between `n and `t). This set of characters can be changed by editing the
following example, which sets the new ending characters for all hotstrings, not just the ones
beneath it:
#Hotstring EndChars
-()[]{}:;'"/\,.?!`n `t
[v1.1.28+]: The ending
characters can be changed while the script is running by calling the Hotstring function as demonstrated below:
Hotstring("EndChars", "-()[]{}:;")
Options
A hotstring's default
behavior can be changed in two possible ways:
1. The #Hotstring directive, which affects all hotstrings physically beneath that
point in the script. The following example puts the C and R options into
effect: #Hotstring c r.
2. Putting options inside a hotstring's first pair of colons. The
following example puts the C and * options (case sensitive and "ending
character not required") into effect for a single hotstring:
:c*:j@::john@somedomain.com.
The list below describes each option. When specifying more than
one option using the methods above, spaces optionally may be included between
them.
* (asterisk): An ending character (e.g. Space, ., or Enter) is not required to trigger the hotstring. For example:
:*:j@::jsmith@somedomain.com
The example above would
send its replacement the moment you type the @ character. When using the #Hotstring directive, use *0 to turn this option
back off.
? (question mark): The hotstring will be triggered even when it is
inside another word; that is, when the character typed immediately before it is
alphanumeric. For example, if :?:al::airline is a hotstring, typing
"practical " would produce "practicairline ".
Use ?0 to turn this option back off.
B0 (B followed by a zero): Automatic backspacing is not
done to erase the abbreviation you type. Use a plain B to turn backspacing back
on after it was previously turned off. A script may also do its own backspacing
via
{bs 5}, which sends 5 Backspace keystrokes. Similarly, it may send ← keystrokes via {left 5}. For example, the following hotstring
produces "<em></em>" and moves the caret 5 places to the
left (so that it's between the tags):
:*b0:<em>::</em>{left
5}
C: Case sensitive: When you
type an abbreviation, it must exactly match the case defined in the script. Use
C0 to turn case sensitivity back off.
C1: Do not conform to typed case. Use this option to make auto-replace hotstrings case
insensitive and prevent them from conforming to the case of the characters you
actually type. Case-conforming hotstrings (which are the default) produce their replacement text in all caps if
you type the abbreviation in all caps. If you type the first letter in caps,
the first letter of the replacement will also be capitalized (if it is a
letter). If you type the case in any other
way, the replacement is sent exactly as defined. When using the #Hotstring directive, C0 can be used to turn this option back off, which makes
hotstrings conform again.
Kn: Key-delay: This
rarely-used option sets the delay between keystrokes produced by
auto-backspacing or auto-replacement. Specify the new delay for n; for example, specify k10 to have a
10ms delay and k-1 to have no delay.
The exact behavior of this option depends on which sending mode is in
effect:
SI (SendInput): Key-delay is ignored because a delay is not
possible in this mode. The exception to this is when SendInput is unavailable, in
which case hotstrings revert to SendPlay mode below (which does obey
key-delay).
SP (SendPlay): A delay of length zero is the default, which for
SendPlay is the same as -1 (no delay). In this mode, the delay is actually a PressDuration rather
than a delay between keystrokes.
SE (SendEvent): A delay of length zero is the default. Zero is
recommended for most purposes since it is fast but still cooperates well with
other processes (due to internally doing a Sleep 0).
Specify k-1 to have no
delay at all, which is useful to make auto-replacements faster if
your CPU is frequently under heavy load. When set to -1, a script's
process-priority becomes an important factor in how fast it can send
keystrokes. To
raise a script's priority, use Process, Priority,, High.
O: Omit the ending character
of auto-replace hotstrings when the replacement is produced. This is useful when you want a
hotstring to be kept unambiguous by still requiring an ending character, but
don't actually want the ending character to be shown
on the screen. For example, if :o:ar::aristocrat is a hotstring, typing "ar" followed by the spacebar
will produce "aristocrat" with no trailing space, which allows you to
make the word plural or possessive without
having to press Backspace. Use O0 (the letter O followed by a zero) to turn
this option back off.
Pn: The priority of the
hotstring (e.g. P1). This rarely-used option has no effect on auto-replace
hotstrings.
R: Send the replacement text raw; that
is, without translating {Enter} to Enter, ^c to Control+C, etc. This option is put into effect automatically for hotstrings
that have a continuation section. Use R0 to turn this option back off.
Note: Text mode may be more reliable. The
R and T options are mutually exclusive.
SI or SP or SE
[v1.0.43+]: Sets the method by which auto-replace
hotstrings send their keystrokes. These options are
mutually exclusive: only one can be in effect at a time. The following
describes each option:
SI stands for SendInput, which
typically has superior speed and reliability than the other modes. Another
benefit is that like SendPlay below, SendInput postpones anything you type
during a hotstring's auto-
replacement text. This prevents your
keystrokes from being interspersed with those of the replacement. When
SendInput is unavailable,
hotstrings automatically use SendPlay instead.
SP stands for SendPlay, which may allow hotstrings to work in a broader variety of
games.
SE stands for SendEvent, which
is the default in versions older than 1.0.43.
If none of the above
options are used, the default mode in [v1.0.43] and later is SendInput.
However, unlike the SI option, SendEvent is used instead of SendPlay when
SendInput is unavailable.
T [v1.1.27+]: Send the
replacement text raw, without
translating each character to a keystroke. For details, see Text mode. Use T0
or R0 to turn this option back off,
or override it with R.
X [v1.1.28+]: Execute.
Instead of replacement text, the hotstring accepts a command or expression to
execute. For example, :X:~mb::MsgBox would cause a message box to be displayed when the user types
"~mb" instead
of auto-replacing it with
the word "MsgBox". This is most useful when defining a large number
of hotstrings which call functions, as it would otherwise require three lines
per hotstring.
When used with the Hotstring function, the X option causes the Replacement parameter to be
interpreted as a label or function name instead of replacement text. However,
the X option has this effect only if it is specified each time the function is called.
Z: This rarely-used option resets the hotstring recognizer after
each triggering of the hotstring. In other words, the script will begin waiting
for an entirely new hotstring, eliminating from consideration anything you
previously typed. This can prevent unwanted triggerings of
hotstrings. To illustrate, consider the following hotstring:
:b0*?:11::
SendInput xx
return
Since the above lacks the Z option, typing 111 (three consecutive
1's) would trigger the hotstring twice because the middle 1 is the last character of the first triggering
but also the first character of the second triggering. By adding the letter Z in front of b0, you would have to
type four 1's instead of three to trigger the hotstring twice. Use Z0 to turn
this option back off.
Long Replacements
Hotstrings that produce a
large amount of replacement text can be made more readable and maintainable by
using a continuation section. For example:
::text1::
(
Any text between the top and bottom parentheses is treated
literally, including commas and percent signs.
By default, the hard carriage return (Enter) between the previous
line and this one is also preserved.
By default, the
indentation (tab) to the left of this line is preserved.
See continuation section for
how to change these default behaviors.
)
The presence of a continuation section also causes the hotstring
to default to raw mode. The only way to override
this special default is to specify the r0 option in each hotstring that has
a continuation section (e.g.
:r0:text1::).
Context-sensitive
Hotstrings
The directives #IfWinActive/Exist can be
used to make selected hotstrings context sensitive. Such hotstrings send a
different replacement, perform a different action, or do nothing at all
depending on the type of window that is
active or exists. For example:
#IfWinActive ahk_class Notepad
::btw::This replacement text will appear only in Notepad.
#IfWinActive
::btw::This replacement text
appears in windows other than Notepad.
AutoCorrect
The following script uses hotstrings to correct about 4700 common
English misspellings on-the-fly. It also includes a Win+H hotkey to make it easy to add more misspellings:
Download: AutoCorrect.ahk (127 KB)
Author: Jim Biancolo and Wikipedia's Lists of Common Misspellings
Remarks
Variable references such as %MyVar% are not currently supported within the replacement text. To work
around this, don't make such hotstrings auto-replace. Instead, use the SendInput command
beneath the abbreviation, followed by
a line containing only the word Return.
To send an extra space or
tab after a replacement, include the space or tab at the end of the replacement
but make the last character an accent/backtick (`). For example:
:*:btw::By the way `
By default, any click of the left or right mouse button will reset
the hotstring recognizer. In other words, the script will begin waiting for an
entirely new hotstring, eliminating from consideration anything you previously
typed (if this is undesirable, specify the line #Hotstring NoMouse anywhere in the script). This "reset upon mouse click"
behavior is the default because each click typically moves the text insertion
point (caret) or sets
keyboard focus to a new control/field. In such cases, it is
usually desirable to: 1) fire a hotstring even if it lacks the question mark option; 2)
prevent a firing when something you type after clicking the mouse accidentally
forms a valid abbreviation with what you typed
before.
The hotstring recognizer checks the active window each time a
character is typed, and resets if a different window is active than before. If
the active window changes but reverts before any characters are typed, the
change is not detected (but the
hotstring recognizer may be reset for some other reason). The hotstring
recognizer can also be reset by calling Hotstring("Reset").
The built-in variable A_EndChar
contains the ending character that you typed to trigger the most recent
non-auto-replace hotstring. If no ending character was required (due to the * option), it will be blank.
A_EndChar is useful when making hotstrings
that use the Send command or whose behavior should vary depending on which
ending character you typed. To send the ending character itself, use SendRaw
%A_EndChar% (SendRaw is
used because characters such as !{} would not be sent
correctly by the normal Send command).
Although commas, percent signs, and single-colons within hotstring
definitions do not need to be escaped,
backticks and those semicolons having a space or tab to their left require it.
See escape sequences for a
complete list.
Although the Send command's
special characters such as {Enter} are supported in auto-replacement text (unless the raw option is used), the hotstring abbreviations themselves do not use this.
Instead, specify `n for the
Enter key and `t (or a literal tab) for Tab (see escape sequences for a
complete list). For example, the hotstring :*:ab`t:: would be triggered when you type "ab" followed by a
tab.
Spaces and tabs are treated
literally within hotstring definitions. For example, the following would
produce two different results: ::btw::by the way and ::btw:: by the way.
Each hotstring abbreviation can be no more than 40 characters
long. The program will warn you if this length is exceeded. By contrast, the
length of hotstring's replacement text is limited to about 5000 characters when
the
sending mode
is at its default of SendInput. That limit can be increased to 16,383
characters by switching to one of the other
sending modes. Furthermore, an unlimited amount of text can be sent by
using SendPlay
%MyVariable% in the body of the
hotstring.
The order in which hotstrings are defined determines their
precedence with respect to each other. In other words, if more than one
hotstring matches something you type, only the one listed first in the script
will take effect. Related topic: context-sensitive hotstrings.
Any backspacing you do is taken into account for the purpose of
detecting hotstrings. However, the use of ↑, →, ↓, ←, PageUp, PageDown, Home, and End to navigate within an editor will cause the
hotstring recognition
process to reset. In other words, it will begin waiting for an
entirely new hotstring.
A hotstring may be typed even when the active window is ignoring
your keystrokes. In other words, the hotstring will still fire even though the
triggering abbreviation is never visible. In addition, you may still press the
Backspace key to undo the most recently
typed keystroke (even though you can't see the effect).
It is possible to Gosub or Goto a
hotstring label by including its first pair of colons (including any option
symbols) in front of its name. For example: Gosub ::xyz. However, jumping to a single-line (auto-replace)
hotstring will do nothing other than
execute a return.
Although hotstrings are not
monitored and will not be triggered during the course of an invisible Input command,
visible Inputs are capable of triggering them.
By default, hotstrings are never triggered by keystrokes produced
by any AutoHotkey script. This avoids the possibility of an infinite loop where
hotstrings trigger each other over and over. In [v1.1.06] and later, this
behaviour can be controlled with
#InputLevel and SendLevel. However, auto-replace hotstrings always use send level 0 and
therefore never trigger hook hotkeys or
hotstrings.
[v1.1.28+]: Hotstrings can
be created dynamically by means of the Hotstring function, which can also modify, disable, or enable the script's
existing hotstrings individually.
The Input command
is more flexible than hotstrings for certain purposes. For example, it allows
your keystrokes to be invisible in the active window (such as a game). It also
supports non-character ending keys such as
Escape.
The keyboard hook is
automatically used by any script that contains hotstrings.
Hotstrings behave identically to hotkeys in the following ways:
They are affected by the Suspend command.
They obey #MaxThreads and #MaxThreadsPerHotkey (but not #MaxThreadsBuffer).
Scripts containing hotstrings are automatically persistent.
Non-auto-replace hotstrings will create a new thread when
launched. In addition, they will update the built-in hotkey variables such as A_ThisHotkey.
Known limitation: On some systems in Java applications, hotstrings
might interfere with the user's ability to type diacritical letters (via dead
keys). To work around this, Suspend can be
turned on temporarily (which
disables all hotstrings).
Function Hotstrings
[v1.1.28+]
One or more hotstrings can
be assigned a function by
simply defining it immediately after the hotstring label, as in this example:
; This example also demonstrates one way to implement case conformity
in a script.
:C:BTW:: ; Typed in
all-caps.
:C:Btw:: ; Typed with only the first letter
upper-case.
: :btw:: ; Typed in any other combination.
case_conform_btw() {
hs := A_ThisHotkey ;
For convenience and in case we're interrupted.
if (hs ==
":C:BTW")
Send BY THE WAY
else if (hs == ":C:Btw")
Send By the way
else
Send by the way
}
For additional details, see
Function Hotkeys.
The Hotstring function can also be used to assign a function or function object
to a hotstring.
Hotstring Helper
Andreas Borutta suggested the following script, which might be
useful if you are a heavy user of hotstrings. By pressing Win+H (or another hotkey of your choice), the currently selected text
can be turned into a hotstring.
For example, if you have "by the way" selected in a word
processor, pressing Win+H will prompt you for its abbreviation (e.g. btw)
and then add the new hotstring to the script. It will then reload the script to
activate the
hotstring.
Note: The Hotstring function can be used to create new hotstrings without reloading.
Take a look at the first example in the
example section of the function's page to see how this could be done.
#h:: ; Win+H hotkey
; Get the text currently selected.
The clipboard is used instead of
; "ControlGet Selected"
because it works in a greater variety of editors
; (namely word processors). Save the current clipboard contents to be
; restored later. Although this
handles only plain text, it seems better
; than nothing:
AutoTrim Off ; Retain any leading and trailing whitespace
on the clipboard.
ClipboardOld = %ClipboardAll%
Clipboard = ;
Must start off blank for detection to work.
Send ^c
ClipWait 1
if ErrorLevel ; ClipWait timed out.
return
; Replace CRLF and/or LF with `n
for use in a "send-raw" hotstring:
; The same is done for any other
characters that might otherwise
; be a problem in raw mode:
StringReplace, Hotstring,
Clipboard, ``, ````, All ; Do this replacement first to avoid
interfering with the others below.
StringReplace, Hotstring,
Hotstring, `r`n, ``r, All ; Using `r
works better than `n in MS Word, etc.
StringReplace, Hotstring,
Hotstring, `n, ``r, All
StringReplace, Hotstring,
Hotstring, %A_Tab%, ``t, All
StringReplace, Hotstring,
Hotstring, `;, ```;, All
Clipboard = %ClipboardOld% ;
Restore previous contents of clipboard.
; This will move the InputBox's
caret to a more friendly position:
SetTimer, MoveCaret, 10
; Show the InputBox, providing the
default hotstring:
InputBox, Hotstring, New Hotstring, Type your abreviation at the
indicated insertion point. You can also edit the replacement text if you
wish.`n`nExample entry: :R:btw`::by the way,,,,,,,, :R: if
ErrorLevel ; The user pressed Cancel.
return
IfInString, Hotstring, :R`:::
{
MsgBox You didn't
provide an abbreviation. The hotstring has not been added.
return
}
; Otherwise, add the hotstring and
reload the script:
FileAppend, `n%Hotstring%,
%A_ScriptFullPath% ; Put a `n at the beginning in case
file lacks a blank line at its end.
Reload
Sleep 200 ; If successful, the
reload will close this instance during the Sleep, so the line below will never
be reached.
MsgBox, 4,, The hotstring just added appears to be improperly
formatted. Would you like to open the
script for editing? Note that the bad hotstring is at the bottom of the script.
IfMsgBox, Yes, Edit
return
MoveCaret:
IfWinNotActive, New Hotstring
return
; Otherwise, move the InputBox's insertion point to where the user
will type the abbreviation.
Send {Home}{Right 3}
SetTimer, MoveCaret, Off
return
Version 1.1.30.00
©2003-2014 Chris Mallett,
portions ©AutoIt
Team and the AHK community
Software License: GNU General Public License
Quick Reference
Getting started:
Text editors with AutoHotkey support
Frequently asked questions
Scripts:
Concepts and conventions: explanations of various things you need to know.
Scripting language: how to
write scripts.
Keyboard and mouse:
Hotkeys (mouse, joystick and keyboard shortcuts)
List of keys, mouse buttons and joystick controls
Other:
Script compatibility - AutoHotkey 1.0 users read this
Acknowledgements
A special thanks to
Jonathan Bennett, whose generosity in releasing AutoIt v2 as free software in 1999 served as an inspiration and
time-
saver for myself and many others worldwide. In
addition, many of AutoHotkey's enhancements to the AutoIt v2 command set, as
well as the Window Spy and the old script
compiler, were adapted directly from the AutoIt v3 source code. So thanks to
Jon and the other
AutoIt authors for those as
well.
Finally, AutoHotkey would not be what it is today without these other individuals.
~ Chris Mallett
List of Keys (Keyboard,
Mouse and Joystick)
Table of Contents
Mouse
General Buttons
Advanced Buttons
Wheel
Keyboard
General Keys
Cursor Control Keys
Numpad Keys
Function Keys
Modifier Keys
Multimedia Keys
Other Keys
Joystick
Hand-held Remote Controls
Special Keys
Mouse
General Buttons
LButton Left
mouse button
RButton Right
mouse button
MButton Middle
or wheel mouse button
Advanced Buttons
XButton1 4th
mouse button. Typically performs the same function as Browser_Back.
XButton2 5th
mouse button. Typically performs the same function as Browser_Forward.
Wheel
WheelDown Turn
the wheel downward (toward you).
WheelUp Turn
the wheel upward (away from you).
[v1.0.48+]:
Scroll to the left or right.
WheelLeft WheelRight
Requires Windows Vista or later. These can be used as hotkeys with
some (but not all) mice which have a second wheel
or support tilting the wheel to either side. In some cases, software bundled
with the mouse must instead be used to control
this feature. Regardless of the particular mouse, Send and Click can
be
used to scroll horizontally in programs which support it.
Keyboard
Note: The names of the letter and number keys are the same as that
single letter or digit. For example: b is the B key and 5 is the 5 key.
Although any single character can be used as a key
name, its meaning (scan code or virtual keycode) depends on the current
keyboard layout. Additionally, some special
characters may need to be escaped or enclosed in braces, depending on the
context. [v1.1.27+]: The letters a-z or A-Z can be used to refer to the
corresponding virtual keycodes (usually vk41-vk5A) even if they are not
included in the
current keyboard layout.
General Keys
CapsLock CapsLock (caps lock key)
Space Space (space bar)
Tab Tab (tabulator key)
Enter (or Return) Enter
Escape (or Esc) Esc
Backspace (or BS) Backspace
Cursor Control Keys
ScrollLock ScrollLock (scroll lock key)
Delete (or Del) Delete
Insert (or Ins) Insert
Home Home
End End
PgUp PageUp (page up key)
PgDn PageDown (page down key)
Up ↑ (up arrow key)
Down ↓ (down arrow key)
Left ← (left arrow key)
Right → (right arrow key)
Numpad Keys
Due to system behavior, the following keys seperated by a slash
are identified differently depending on whether NumLock is ON or OFF. If NumLock is OFF
but Shift is pressed, the system temporarily releases Shift and acts as though NumLock is ON.
Numpad0 / NumpadIns 0 / Insert
Numpad1 / NumpadEnd 1 / End
Numpad2 / NumpadDown 2 / ↓
Numpad3 / NumpadPgDn 3 / PageDown
Numpad4 / NumpadLeft 4 / ←
Numpad5 / NumpadClear 5 / typically does nothing
Numpad6 / NumpadRight 6 / →
Numpad7 / NumpadHome 7 / Home
Numpad8 / NumpadUp 8 / ↑
Numpad9 / NumpadPgUp 9 / PageUp
NumpadDot / NumpadDel . / Delete
NumLock NumLock (number lock key)
NumpadDiv / (division)
NumpadMult * (multiplication)
NumpadAdd + (addition)
NumpadSub - (subtraction)
NumpadEnter Enter
Function Keys
F1 - F24 The 12 or
more function keys at the top of most keyboards.
Modifier Keys
LWin Left
Win. Corresponds to the <# hotkey
prefix.
Right Win. Corresponds to the ># hotkey prefix.
Note: Unlike Control/Alt/Shift, there
is no generic/neutral "Win" key because the OS does not support
it. However, hotkeys with the # modifier can be triggered by either Win key.
Control
(or Ctrl) Control. As a hotkey (Control::) it fires upon release
unless it has the tilde prefix. Corresponds to the ^
hotkey prefix.
Alt Alt. As a hotkey (Alt::) it fires upon
release unless it has the tilde prefix. Corresponds to the ! hotkey
prefix.
Shift Shift. As a hotkey (Shift::) it fires upon
release unless it has the tilde prefix. Corresponds to the +
hotkey prefix.
LControl (or LCtrl) Left Control.
Corresponds to the <^ hotkey prefix.
RControl (or RCtrl) Right
Control. Corresponds to the >^ hotkey prefix.
LShift Left
Shift. Corresponds to the <+ hotkey prefix.
RShift Right
Shift. Corresponds to the >+ hotkey prefix.
LAlt Left Alt. Corresponds to the <! hotkey prefix.
Right Alt. Corresponds to the >! hotkey prefix.
RAlt
Note: If your keyboard layout has AltGr instead of RAlt, you can
probably use it as a hotkey prefix via <^>! as described here. In
addition, LControl &
RAlt:: would make AltGr itself into a hotkey.
Multimedia Keys
The function assigned to each of the keys listed below can be
overridden by modifying the Windows registry. This table shows the
default function of each key on most versions of Windows.
Browser_Back Back
Browser_Forward Forward
Browser_Refresh Refresh
Browser_Stop Stop
Browser_Search Search
Browser_Favorites Favorites
Browser_Home Homepage
Volume_Mute Mute
the volume
Volume_Down Lower
the volume
Volume_Up Increase
the volume
Media_Next Next
Track
Media_Prev Previous
Track
Media_Stop Stop
Media_Play_Pause Play/Pause
Launch_Mail Launch
default e-mail program
Launch_Media Launch
default media player
Launch_App1 Launch
My Computer
Launch_App2 Launch
Calculator
Other Keys
AppsKey Menu. This is the key that
invokes the right-click context menu.
PrintScreen PrintScreen
CtrlBreak Ctrl+Break
Pause Pause
Break Break. Since this is synonymous with Pause, use ^CtrlBreak in hotkeys instead of ^Pause or ^Break.
Help Help. This probably doesn't
exist on most keyboards. It's usually not the same as F1.
Sleep Sleep. Note that the sleep key on some keyboards might not work with
this.
SCnnn Specify for nnn the
scan code of a key. Recognizes unusual keys not mentioned above. See Special Keys
for details.
Specify for nn the
hexadecimal virtual key code of a key. This rarely-used method also prevents
certain types of hotkeys
from requiring the keyboard hook. For example, the following hotkey does not use the
keyboard hook, but as a side-effect it is triggered
by pressing either Home or NumpadHome:
^VK24::MsgBox You pressed Home or
NumpadHome while holding down Control.
Known limitation: VK hotkeys that are forced to use the keyboard hook, such as *VK24 or ~VK24, will
VKnn
fire for only one of the keys, not both (e.g. NumpadHome but not Home). For more information about the VKnn method, see Special Keys.
Warning: Only Send, GetKeyName, GetKeyVK, GetKeySC and #MenuMaskKey support combining
VKnn and SCnnn. [v1.1.27+]: The presence of an invalid suffix
prevents VKnn from being recognized. For example, vk1Bsc001:: raises an error in v1.1.27+, but
sc001 was ignored (had no effect) in previous
versions.
Joystick
Joy1 through Joy32: The
buttons of the joystick. To help determine the button numbers for your
joystick, use this test script. Note
that
hotkey prefix symbols such as
^ (control) and + (shift) are not supported (though GetKeyState can be used as a substitute). Also note that
the pressing of joystick buttons always "passes
through" to the active window if that window is designed to detect the
pressing of
joystick buttons.
Although the following
Joystick control names cannot be used as hotkeys, they can be used with GetKeyState:
JoyX, JoyY, and JoyZ: The X
(horizontal), Y (vertical), and Z (altitude/depth) axes of the joystick.
JoyR: The rudder or 4th
axis of the joystick.
JoyU and JoyV: The 5th and
6th axes of the joystick.
JoyPOV: The point-of-view
(hat) control.
JoyName: The name of the
joystick or its driver.
JoyButtons: The number of buttons supported by the
joystick (not always accurate).
JoyAxes: The number of axes
supported by the joystick.
JoyInfo: Provides a
string consisting of zero or more of the following letters to indicate the
joystick's capabilities: Z (has Z
axis), R (has R axis), U (has U axis), V (has V
axis), P (has POV control), D (the POV control has a limited number of
discrete/distinct settings), C
(the POV control is continuous/fine). Example string: ZRUVPD
Multiple Joysticks: If the computer has more than one joystick and
you want to use one beyond the first, include the joystick number
(max 16) in front of the control name. For example, 2joy1 is the
second joystick's first button.
Note: If you have trouble getting a script to recognize your
joystick, one person reported needing to specify a joystick number other than
1 even though only a single joystick was present. It
is unclear how this situation arises or whether it is normal, but experimenting
with
the joystick number in the joystick test script can help determine if this applies to your system.
See Also:
Joystick remapping: methods of sending keystrokes and mouse clicks with a joystick.
Joystick-To-Mouse script: using a joystick as a mouse.
Hand-held Remote Controls
Respond to signals from hand-held remote controls via the WinLIRC client script.
Special Keys
If your keyboard or mouse
has a key not listed above, you might still be able to make it a hotkey by
using the following steps:
1. Ensure that at least one script is running
that is using the keyboard hook. You can
tell if a script has the keyboard hook by opening
its main window and selecting "View->Key history"
from the menu bar.
2. Double-click that
script's tray icon to open its main window.
3. Press one of the
"mystery keys" on your keyboard.
4. Select the menu item
"View->Key history"
5. Scroll down to the
bottom of the page. Somewhere near the bottom are the key-down and key-up
events for your key. NOTE:
Some keys do not generate events and thus will not be visible
here. If this is the case, you cannot directly make that particular key
a hotkey because your keyboard driver or hardware handles it at a
level too low for AutoHotkey to access. For possible solutions,
see further below.
6. If your key is
detectable, make a note of the 3-digit hexadecimal value in the second column
of the list (e.g. 159).
7. To define this key as
a hotkey, follow this example:
SC159:: ; Replace 159 with your key's value.
MsgBox, %A_ThisHotkey% was pressed.
return
Reverse direction: To remap some other key to become a "mystery key", follow
this example:
; Replace 159 with the value
discovered above. Replace FF (if needed) with the
; key's virtual key, which can be discovered in the first column
of the Key History screen.
#c::Send {vkFFsc159}
Alternate solutions: If your key or mouse button is not
detectable by the Key History screen,
one of the following might help:
1. Reconfigure the software that came with
your mouse or keyboard (sometimes accessible in the Control Panel or Start
Menu) to
have the "mystery key" send some other keystroke. Such a
keystroke can then be defined as a hotkey in a script. For example, if
you configure a mystery key to send Control+F1, you can then indirectly make that key as a
hotkey by using ^F1:: in a script.
2. Try AHKHID. You can
also try searching the forum for a keywords like RawInput*, USB HID or AHKHID.
3. The following is a last resort and
generally should be attempted only in desperation. This is because the chance
of success is low
and it may cause unwanted side-effects that are difficult to undo:
Disable or remove any extra software that came with your keyboard
or mouse or change its driver to a more standard one such as
the one built into the OS. This assumes there is such a driver for
your particular keyboard or mouse and that you can live without
the features provided by its custom driver and software.